std vector 的先前内容在迭代期间被替换

Previous content of std vector is replaced during iteration

我正在编写一个程序,它应该在图中找到一个有根的生成树,以及连接根和生成树中其他顶点的所有唯一路径。我正在尝试仅使用一种功能执行两种操作:

void Spanning_tree_finder(){

    int * v=Add_edges(s1); int control=0; int size;

    for(int i=0; i<_g.GetE(); i++){

        if(control==0 && v[i]==1) {

        s1[i]=1; control=1; 
        size=_v.size(); 
            for(int j=0; j<size; j++){

                if(_v[j].Getv2()==_g.GetEdge1(i)){
                Path pnew=_v[j];

                pnew.Setv2(_g.GetEdge2(i));
                pnew.Setp(i); 
                _v.push_back(pnew); 
                };

                if(_v[j].Getv2()==_g.GetEdge2(i)){
                Path pnew=_v[j];
                pnew.Setv2(_g.GetEdge1(i));
                pnew.Setp(i);
                _v.push_back(pnew); 
                };
            };

        Spanning_tree_finder();

        };
    };

    return;
};

为了上下文,该函数迭代构建生成树,在过程结束时包含在 s1 中,通过获取一棵树,也包含在 s1 中,搜索所有相邻边使用函数 Add_edges 并因此将相邻边之一添加到前一棵树中。然后再次调用该函数(请注意,Add_EdgesSpanning_tree_finder 都是 class 的一部分,而 s1 是此类 class 的私有成员)。在此过程中,该函数还通过搜索连接根与新引入边的非松散顶点的先前路径并将该路径添加到该路径来构造连接根与与新引入的相邻边相关联的松散顶点的路径新引入的边缘。路径都存储在路径向量中,_v。我知道这个解释有点绕,但我希望它是清楚的。

然而,这个函数有一个问题,因为似乎在每次迭代中,_v 中包含的所有路径都被替换为当前迭代中获得的路径。 _v 不是获得 _v.size() 个不同的路径,而是包含 _v.size() 个相同路径的副本,并且这在每次迭代中都成立。我不明白为什么会发生这种情况,因为在我看来该函数永远不会访问先前添加的元素。 我希望我解释的问题很清楚,我很乐意提供任何进一步的说明。

编辑:更具体地说,我认为有问题的代码行是

for(int j=0; j<size; j++){

            if(_v[j].Getv2()==_g.GetEdge1(i)){
            Path pnew=_v[j];

            pnew.Setv2(_g.GetEdge2(i));
            pnew.Setp(i); 
            _v.push_back(pnew); 
            };

            if(_v[j].Getv2()==_g.GetEdge2(i)){
            Path pnew=_v[j];
            pnew.Setv2(_g.GetEdge1(i));
            pnew.Setp(i);
            _v.push_back(pnew); 
            };
};

问题的核心是pnew是如何插入到_v中的。不是在向量末尾添加元素 pnew,而是将 _v 中的所有元素替换为 pnew

听起来确实像 _v 中的对象有一些通过指针访问的数据,并且您正在通过修改您认为是新的对象来修改 _v 中已有的对象。

Crystal 球说 Path pnew = _v[j] 复制一个现有的 Path 对象,其中包含一些指向数据的指针。指针将被复制到新对象,但指向相同的位置,因此 Setv2Setp 等修饰符将更改所有对象的数据。

尝试通过用其他东西(如向量)替换显式指针来修复路径,或者编写正确处理这些指针字段的适当的复制构造函数和赋值运算符(通过分配新内存和复制内容)。