矢量迭代器不兼容

vector iterators incompatible

本文关键字:不兼容 迭代器      更新时间:2023-10-16

我目前正在为C++开发一个图库,现在遇到了在运行时调试模式下出现断言错误的问题。我还看了SO上的其他问题,但没有一个问题和答案能让我找到解决方案。在一些论坛上阅读后,我的印象是,发生这种错误是因为一旦向量内容发生变化,迭代器就会失效。(例如,当使用erase()时)但正如您在我的代码中看到的,我并没有修改向量,只是迭代。

错误在我用//ASSERTION标记的行中。奇怪的是,neighbor_it没有指向(*vertex_it)->neighbors()中的第一个对象,而是指向0xfeeefeee。当调试代码时,我可以清楚地看到邻居向量至少包含一个项。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;
}

再次感谢您的回答!:)

我的猜测是,在您提供的上下文有限的情况下,neighbours()返回std::vector<edge*>的副本,而不是引用,即std::vector<edge*>&。所以begin()调用后临时对象被处理掉,得到的迭代器指向垃圾。

我猜remove_edge修改了neighbor_it的底层容器,从而使其无效,但如果没有看到更多的代码,我就无法确定。

如果是这种情况,一个可能的解决方案是将迭代器返回到删除的元素之后的下一个元素,例如std::vector::erase