向量迭代器不兼容 [英] vector iterators incompatible

查看:337
本文介绍了向量迭代器不兼容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用一个图形库的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆