2011-05-31 22 views
4

私は現在C++のグラフライブラリで作業していますが、ランタイム中にデバッグモードでアサーションエラーが発生するところで立ち往生しています。私はまた、ここでいくつかの他の質問を見ましたが、質問と回答のいずれも私に解決策をもたらしませんでした。いくつかのフォーラムでは、ベクタの内容が変更されるとすぐにイテレータが無効になるため、このエラーが発生するという印象があります。 (例えば、erase()を使用している場合)しかし、私のコードで見ることができるように、私はベクトルを修正するのではなく、反復するだけです。ベクトルの反復子が互換性がありません

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

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(); 

    // 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; 
} 

もう一度お返事いただきありがとうございます。 :)

+3

remove_edge()は何ですか?あなたのループで使用されているデータに触れていますか? – Macke

+0

'neighbors()'はどのように定義されていますか? – sergio

+0

remove_edgeは、vertex_itが指している頂点からエッジ(隣接関係)を削除します。しかし、アサーションが解雇されたとき、私はremove_edgeが呼び出される行まで到達しませんでした。 – Exa

答えて

11

あなたが提供した文脈が限定されているとすれば、は、std::vector<edge*>&の代わりにstd::vector<edge*>のコピーを返します。したがって、begin()の呼び出し後に一時オブジェクトを処理し、イテレータポイントを取得してゴミとする。

+0

おそらく初心者の間違いですが、そうでした。私は、これらの間違いを避けるために参考にしていきます。ありがとうございます! – Exa

1

remove_edgeは、neighbor_itの基になるコンテナを変更して無効にすると思いますが、コードの多くを見ることはできません。

この場合、可能であれば、イテレータを、削除された要素の次の要素に返すことが考えられます(例:std::vector::erase)。

+0

上記の私のコメントを参照してください。 – Exa

+0

もう、別の問題です。削除後、イテレータは無効になります。私は1つのエッジを削除した後に反復処理を行う方法を理解する必要があります。ありがとうございました。 – Exa

+0

解決策については私の編集した質問を参照してください。 – Exa

関連する問題