C++:从另一个向量指向对象的指针向量

C++: Vector of Pointers to Objects from another Vector

我有两个class,类似这样:

class A
{
public:
    B* ptr1;
}

class B
{
public:
    std::vector<A*> list;
}

在主要实现中,我正在做这样的事情:

int main() {

// there are a lot more A objects than B objects, i.e. listOfA.size() >>> listOfB.size()
std::vector<A> listOfA;
std::vector<B> listOfB; 

while (//some loop)
{
    listOfB[jj].list.push_back( &(listofA[ii]) );
    listOfA[ii].ptr1 = &( listOfB[jj] );
}

} // int main end

基本上是这样的。很多A对象被分配给一个B对象,这些A对象作为指针存储在那个指针向量中。此外,这些 A 对象中的每一个都获得指向它们所属的 B 对象的指针。对于上下文,我基本上是在使用 运行-length-encoding(用于图像分割)进行连通分量算法,其中 class A 是线段,class B 是最终线段图像中的对象。

所以,classB中vector的指针都指向存储在regular vector中的Objects。当常规向量超出范围时,应该删除这些对象,对吗?我读过像 class B 这样的指针向量通常需要编写一个手动析构函数,但我认为这里不应该是这种情况...

我问的原因当然是因为我的代码总是崩溃。我正在使用 Asus Xtion Pro 相机获取图像,然后对每张图像执行算法。奇怪的是,每当我用力摇动相机时,程序就会崩溃。当相机静止或仅移动一点点或缓慢移动时,什么也不会发生。此外,当我使用不同的算法(也连接组件,但没有 运行-length-encoding 并且也不使用指针)时,无论我如何摇动相机,都不会崩溃。此外,在调试模式下(运行 比发布模式慢得多),也没有崩溃。

我尝试为 class B 中的指针向量创建一个析构函数,但它导致了 "block is valid" 错误,所以我猜它删除了两次。 我还尝试用 c++11 std::shared_ptr 替换每个指针,但这只会产生非常不规则的行为,并且当我摇动相机时代码仍然崩溃。

我基本上只想知道在内存泄漏和指针处理方面,上面显示的代码是否正常,或者代码中是否存在可能导致崩溃的错误。

编辑(已解决): 解决方案(参见已接受的答案)是确保矢量 'listOfB' 在 运行 期间不会调整大小-time,例如使用 'reserve()' 为它预留足够的 space。这样做之后,一切正常!显然它起作用了,因为如果向量 'listOfB' 被调整大小(通过 push_back()),其中 B 实例的内部内存地址也会改变,导致 A 实例中的指针(指向到 B 实例)现在指向错误的地址 - 从而导致麻烦,导致崩溃。

关于相机抖动,显然,相机抖动导致图片非常模糊,需要分割的元素很多,从而增加了对象的数量(即导致 listOfB 需要更大的尺寸)。于是,谜底揭晓!非常感谢! :-)

假设您在构建网络的方式上没有犯错,您应该没问题。您将不得不 post 更多代码来评估它。此外,在更改其中一个后,您不能使用 vectors 中的任何一个,因为如果它们重新分配其成员,则所有指向它们的指针都会失效。但是使用 原始指针 托管对象 是构建 网络 .

的正确方法

通过托管对象我的意思是保证其生命周期比网络持续时间更长并且其内存将自动释放的对象。所以它们应该是由某种智能指针.

管理的容器或对象的元素

不过听起来您遇到了硬件问题。

我认为设计有问题。 listofB 将增长(你做 push_backs)并重新分配其内部数据数组,使存储在 A 实例的指针中的所有地址无效。通常的算法会将数据大小增加 2 倍,这可以解释如果没有太多数据到达,您可以暂时使用。此外,只要旧数据的内存仍在程序的地址 space 中(特别是如果它在同一内存页上,例如因为新数据也适合它),程序访问它可能不会崩溃,只会检索旧数据。

更具建设性的说明:如果您提前知道最大元素,您的解决方案就会奏效,这可能很难(假设您明年会得到一台 4k 相机 ;-))。在那种情况下,顺便说一下,你可以只使用一个简单的静态数组。

或许您也可以使用 std::map 来存储 A 对象,而不是简单的向量列表 A。每个 A 对象都需要某种类型的唯一 ID(在最简单的情况下,A 中的静态计数器)用作映射中的键。 Bs 将存储密钥,而不是 As 的地址。