向量迭代器不兼容 [英] vector iterators incompatible
问题描述
我目前正在使用一个图形库的C ++,现在陷入了一个点,我在运行时在调试模式下得到一个断言错误。我也看了一些其他问题在这里的SO,但没有一个问题和答案导致我一个解决方案。在一些论坛阅读后,我有一个印象,这种错误发生,因为迭代器变得无效,一旦矢量内容改变。 (例如当使用 erase()
)但是正如你在代码中可以看到的,我不是修改向量,只是迭代。
错误在标有 // ASSERTION
的行中。奇怪的是 neighbor_it
不指向(* vertex_it) - > neighbors(
),但到 0xfeeefeee
。当通过代码调试时,我可以清楚地看到,neighbors-vector包含至少一个项目。不应 neighbor_it
指向此向量中的第一个对象?
有关详细信息: m_vertices
是图形中所有顶点的向量, vertex :: neighbors()
返回一个边的向量邻居/目的地顶点)。在这种方法中,我想删除指向某个顶点的所有边。如果已找到并删除相应的边,则返回true,如果没有边指向 p_vertex
,则返回false。
bool graph :: remove_edges_pointing_to(vertex * p_vertex)
{
bool res = false;
std :: vector< vertex *> :: iterator vertex_it = m_vertices.begin();
//遍历所有顶点
while(vertex_it!= m_vertices.end())
{
//顶点邻居的第一个元素的迭代器
std :: vector< edge *> :: iterator neighbor_it =(* vertex_it) - > neighbors()。begin();
//遍历每个顶点的所有后续节点
while(neighbor_it!=(* vertex_it) - > neighbors()。end())// ASSERTION
{
if((* neighbor_it) - > dest()== p_vertex)
{
if((* vertex_it) - > remove_edge(* neighbor_it))
{
res = true;
}
}
neighbor_it ++;
}
vertex_it ++;
}
return res;
}
EDIT :(解决方案)
好吧,这里是我的新代码可以正常工作。 remove_edge()
现在返回一个迭代器到向量中的下一个对象,它删除了边。此外, neighbors()
现在返回一个引用
bool graph :: remove_edges_pointing_to(vertex * p_vertex)
{
bool res = false;
std :: vector< vertex *> :: iterator vertex_it = m_vertices.begin();
//遍历所有顶点
while(vertex_it!= m_vertices.end())
{
//顶点邻居的第一个元素的迭代器
std :: vector< edge *> :: iterator neighbor_it =(* vertex_it) - > neighbors()。begin();
//遍历每个顶点的所有后继
while(neighbor_it!=(* vertex_it) - > neighbors()。end())
{
if((* neighbor_it) - > dest()== p_vertex)
{
neighbor_it =(* vertex_it) - > remove_edge(* neighbor_it);
res = true;
}
else
{
neighbor_it ++;
}
}
vertex_it ++;
}
return res;
}
再次感谢您的回答! :)
我猜你在提供的有限内容是 neighbors c $ c>返回
std :: vector< edge *>
的副本,而不是引用,即 std :: vector< edge * &
。所以在 begin()
后调用临时对象被处理,并获得迭代器指向垃圾。
I'm currently working on a graph library for C++ and now got stuck at a point where I get an assertion error in debug mode during runtime. I also had a look an some other question here on SO but none of the questions and answers lead me to a solution. After reading in some forums I have the impression that this error happens because iterators become invalid as soon as the vector content is changed. (for example when using erase()
) But as you can see in my code, I'm not modifying the vector, just iterating.
The error is in the line I marked with //ASSERTION
. The strange thing is that neighbor_it
doesn't point to the first object in (*vertex_it)->neighbors(
) but to 0xfeeefeee
. When debugging through the code I can clearly see that the neighbors-vector contains at least one item. Shouldn't neighbor_it
point to the first object in this vector?
For further information: m_vertices
is a vector of all vertices in a graph and vertex::neighbors()
returns a vector of edges (which have a pointer to the neighbor/destination vertex). In this method I want to remove all edges pointing to a certain vertex. Returns true if an according edge has been found and removed, false if there is no edge pointing to p_vertex
.
bool graph::remove_edges_pointing_to( vertex* p_vertex )
{
bool res = false;
std::vector<vertex*>::iterator vertex_it = m_vertices.begin();
// iterate through all vertices
while( vertex_it != m_vertices.end() )
{
// iterator on first element of neighbors of vertex
std::vector<edge*>::iterator neighbor_it = (*vertex_it)->neighbors().begin();
// iterate through all successors of each vertex
while( neighbor_it != (*vertex_it)->neighbors().end() ) //ASSERTION
{
if( (*neighbor_it)->dest() == p_vertex )
{
if( (*vertex_it)->remove_edge( *neighbor_it ) )
{
res = true;
}
}
neighbor_it++;
}
vertex_it++;
}
return res;
}
EDIT: (Solution)
Alright, here is my new code which works properly. remove_edge()
now returns an iterator to the next object in the vector it removed the edge from. In addition neighbors()
now returns a reference to the according vector.
bool graph::remove_edges_pointing_to( vertex* p_vertex )
{
bool res = false;
std::vector<vertex*>::iterator vertex_it = m_vertices.begin();
// iterate through all vertices
while( vertex_it != m_vertices.end() )
{
// iterator on first element of neighbors of vertex
std::vector<edge*>::iterator neighbor_it = (*vertex_it)->neighbors().begin();
// iterate through all successors of each vertex
while( neighbor_it != (*vertex_it)->neighbors().end() )
{
if( (*neighbor_it)->dest() == p_vertex )
{
neighbor_it = (*vertex_it)->remove_edge( *neighbor_it );
res = true;
}
else
{
neighbor_it++;
}
}
vertex_it++;
}
return res;
}
Thanks again for your answers! :)
My guess, given limited context you provided, is that neighbours()
returns copy of std::vector<edge*>
, instead of reference, i.e. std::vector<edge*>&
. So after begin()
call temporary object is disposed, and obtained iterator points to rubbish.
这篇关于向量迭代器不兼容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!