4

現在、C ++のグラフライブラリに取り組んでいますが、実行時にデバッグモードでアサーションエラーが発生する時点でスタックします。私はまた、ここでSOに関するいくつかの他の質問を調べましたが、質問と回答のどれも私を解決策に導きません。いくつかのフォーラムを読んだ後、ベクターの内容が変更されるとすぐにイテレーターが無効になるため、このエラーが発生するという印象を受けました。(たとえば、を使用する場合erase())しかし、私のコードでわかるように、ベクトルを変更するのではなく、反復するだけです。

エラーは、私が。でマークした行にあり//ASSERTIONます。奇妙なことに、 )neighbor_itの最初のオブジェクトではなく、を指しているということです。コードをデバッグすると、neighbors-vectorに少なくとも1つのアイテムが含まれていることがはっきりとわかります。このベクトルの最初のオブジェクトを指すべきではありませんか?(*vertex_it)->neighbors(0xfeeefeeeneighbor_it

詳細情報:m_verticesはグラフ内のすべての頂点vertex::neighbors()のベクトルであり、エッジのベクトルを返します(隣接/宛先頂点へのポインターがあります)。この方法では、特定の頂点を指すすべてのエッジを削除します。対応するエッジが見つかって削除された場合はtrueを返し、を指すエッジがない場合はfalseを返します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;
}

編集:(解決策)

さて、これが正しく動作する私の新しいコードです。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;
}

回答ありがとうございます!:)

4

2 に答える 2

11

あなたが提供した限られたコンテキストを考えると、参照の代わりに のneighbours()コピーを返す、つまり. したがって、呼び出し後、一時オブジェクトが破棄され、取得されたイテレータはゴミを指します。std::vector<edge*>std::vector<edge*>&begin()

于 2011-05-31T13:06:05.570 に答える
1

remove_edgeの基になるコンテナーが変更され、それによって無効になると思いneighbor_itますが、コードをもっと見ないと確信が持てません。

この場合、考えられる解決策は、削除された要素の次の要素にイテレータを返すことstd::vector::eraseです。

于 2011-05-31T12:56:05.427 に答える