Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么std::vector迭代器在重新分配其他向量时无效?_C++_Vector_Stl_Implementation_Realloc - Fatal编程技术网

C++ 为什么std::vector迭代器在重新分配其他向量时无效?

C++ 为什么std::vector迭代器在重新分配其他向量时无效?,c++,vector,stl,implementation,realloc,C++,Vector,Stl,Implementation,Realloc,这与关于这个话题的其他问题不完全相同。我刚刚偶然发现了一件非常奇怪的事情,不知道这是怎么发生的 struct Edge{ int vertex_a{ 0 }; int vertex_b{ 0 }; }; typedef std::vector<Edge> EdgeList; struct Vertex{ std::vector<int> edge_indices; }; typedef std::vector<Vertex> Ver

这与关于这个话题的其他问题不完全相同。我刚刚偶然发现了一件非常奇怪的事情,不知道这是怎么发生的

struct Edge{
    int vertex_a{ 0 };
    int vertex_b{ 0 };
};
typedef std::vector<Edge> EdgeList;

struct Vertex{
    std::vector<int> edge_indices;
};

typedef std::vector<Vertex> VertexList;

    void ContractEdge(int edge_index){
            static int iter = 0;
            ++iter;
            auto& edge = edge_list[edge_index];
            auto& vertex_a = vertex_list[edge.vertex_a - 1];
            auto& vertex_b = vertex_list[edge.vertex_b - 1];
            auto dead_vertex_index = edge.vertex_b;
            std::vector<int> self_edge_array;
            auto& indices = vertex_b.edge_indices;

            for (auto it = indices.begin(); it != indices.end();++it){
                auto current_index = *it;
                auto& edge_of_b = edge_list[current_index];
                if (edge_of_b.vertex_a == dead_vertex_index){
                    edge_of_b.vertex_a = edge.vertex_a;
                }
                if (edge_of_b.vertex_b == dead_vertex_index){
                    edge_of_b.vertex_b = edge.vertex_a;
                }
                if (edge_of_b.vertex_a == edge_of_b.vertex_b){
                    self_edge_array.push_back(current_index);
                }
                else{
//this is the line where reallocation happens
                    vertex_a.edge_indices.push_back(current_index);
                }
            }
            RemoveVertexFromGraph(dead_vertex_index);
            int d = 0;
            for (auto& x : edge_list){
                if ((x.vertex_a > vertex_list.size()) || (x.vertex_b > vertex_list.size()))
                    ++d;
            }
            if (d)
                ++d;

            std::sort(self_edge_array.rbegin(), self_edge_array.rend());
            for (auto self_edge : self_edge_array){
                RemoveEdgeFromGraph(self_edge);
            }
        }
struct-Edge{
int顶点_a{0};
int顶点_b{0};
};
typedef std::矢量边缘列表;
结构顶点{
向量边缘指数;
};
typedef std::向量顶点列表;
void ContractEdge(int-edge\u索引){
静态int-iter=0;
++iter;
自动&边缘=边缘列表[边缘索引];
自动&顶点_a=顶点_列表[edge.vertex_a-1];
自动&顶点_b=顶点_列表[edge.vertex_b-1];
自动停止顶点索引=edge.vertex\u b;
std::向量自_边_数组;
自动索引和索引=顶点索引和边索引;
for(auto it=index.begin();it!=index.end();+it){
自动当前_索引=*it;
自动&edge\u of_b=边缘列表[当前索引];
if(顶点的边=死顶点索引){
顶点的边=顶点的边;
}
if(顶点的边=死顶点索引){
顶点的边=顶点的边;
}
if(顶点的边=顶点的边){
自我边缘数组。向后推(当前索引);
}
否则{
//这是重新分配发生的地方
顶点索引、边索引、后推索引(当前索引);
}
}
RemoveVertexFromGraph(死顶点索引);
int d=0;
用于(自动和x:edge_列表){
if((x.vertex_a>vertex_list.size())||(x.vertex_b>vertex_list.size())
++d;
}
如果(d)
++d;
排序(self_edge_array.rbegin(),self_edge_array.rend());
for(自动自\u边缘:自\u边缘\u阵列){
RemoveEdgeFromGraph(自_边);
}
}
在这个函数的中间,我对一个顶点的索引向量进行迭代,并偶尔将一些值推回到另一个顶点的索引向量

在运行这段代码时,我开始收到错误消息“Vector iterator not icrementable”。 我决定更仔细地调试,发现当我在这里执行一定量的
push\u back
s
顶点a.edge\u索引。push\u back(当前索引)
,并且向量的大小和容量都是19时,向量实现调用
\u Reserve(1)
方法,该方法调用一些重新分配方法。
之后,索引向量会自动重新分配,其中的所有指针都指向另一个内存块。这就是为什么自动it迭代器不能递增,也不能比较,因为它指向错误的位置时无效。

谢谢您的评论。事实证明,在问题发生的那一刻,我实际上是在将_向后推,与我迭代的向量相反。 当然,这会使迭代器失效。 因此,问题出现在糟糕的数据组织和糟糕的编码风格中。 我现在正在看你的评论,我现在明白了我的代码非常糟糕。谢谢你这么说。 我也没有对整个代码进行审查,因为我认为这已经足够了,但我确信我至少可以证明它是一个类,并且它有一些成员。 并揭示更多的结构。再次对此表示歉意。 我想我可能需要想出一些其他的数据结构,可能在内部算法完成之前不进行任何动态重新分配。我知道,0和1的索引也很蹩脚。我只是在做一个课程任务,任务在txt文件中,有基于1的索引


是的,d和iter用于断点,问题是?你可能会问为什么
std::vector
不通过
realloc
扩展当前分配,而不是在需要时分配新内存?由于有如此多的间接性,你似乎已经设法推回到你正在遍历的向量上。如果你没有整理出一个完整(但请尽量少)的例子。提示:检查向量的地址,例如在调试器中,或通过跟踪输出语句。是。似乎是这样。问题很明显,不是吗?在标题里。所以我怎么能把你推回另一个向量呢?)你的代码太难理解了。。。您想做什么?可能更容易的是在读/写文件时转换这些索引,以避免潜在的陷阱。除非有帮助,否则不要让文件格式泄漏到您的表示中。此外,我认为您的代码并不像一些人所说的那么糟糕——正如前面所说的,一个想要使用索引表示来表示邻接而不是指针的图形结构不可避免地需要涉及很多更显式的间接(针对容器和索引)。对我来说,诀窍是如果你喜欢迭代器的样式,就不要混合迭代器——否则,请检查一个好的顺序/固定alloc,并使用指针。。。。。。以及单独分配的节点,至少在您真正熟悉这些结构的最低级别实现之前是这样。