【发布时间】:2015-11-20 21:30:04
【问题描述】:
这与该主题的其他问题并不完全相同。我刚刚偶然发现了一些非常奇怪的事情,无法理解这是怎么发生的。
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);
}
}
在这个函数的中间,我正在迭代一个顶点的索引向量,并偶尔将一些值 push_back 到另一个顶点的索引向量。
在运行此代码时,我开始收到错误消息“Vector iterator not icrementable”。
我决定再仔细调试一下,发现当我在vertex_a.edge_indices.push_back(current_index)这里做了一定数量的push_backs,并且vector的大小和容量都是19时,vector实现调用了_Reserve(1)方法,它调用了一些重新分配方法。
之后,索引向量会自动重新分配,其中的所有指针都指向另一个内存块。这就是为什么 auto it 迭代器不能进行比较,也不能增加,因为指向错误的地方它变得无效。
【问题讨论】:
-
问题是?
-
您可能会问为什么
std::vector不通过realloc扩展其当前分配,而是在需要时分配新内存? -
有了这么多的间接性,您似乎已经设法退回到您正在遍历的向量上。如果您无法对其进行整理,请发布 complete(但请尽量少)示例。整理的提示:检查向量的地址,例如在调试器中,或通过跟踪输出语句。
-
是的。似乎是这样。这个问题很明显,不是吗?它在标题中。所以。我怎么能 push_back 到另一个向量上?)
-
你的代码太难理解了……你想做什么?
标签: c++ vector stl implementation realloc