我目前正在开发一个用于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();
// 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;
}
编辑:(解决方案)
好的,这是我的新代码,它正常工作。 remove_edge()
现在将迭代器返回到它从中移除边的向量中的下一个对象。此外,neighbors()
现在会将引用返回到相应的向量。
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;
}
再次感谢您的回答! :)
答案 0 :(得分:11)
我的猜测,鉴于您提供的上下文有限,neighbours()
会返回std::vector<edge*>
的副本,而不是引用,即std::vector<edge*>&
。所以在begin()
调用临时对象之后,获得迭代器指向垃圾。
答案 1 :(得分:1)
我猜我会remove_edge
修改neighbor_it
的基础容器,从而使其无效,但如果没有看到更多代码,我就无法确定。
如果是这种情况,可能的解决方案是将迭代器返回到删除后的下一个元素,例如由std::vector::erase
完成。