2016-05-31 12 views
0

に変換最近、私が最近読んだ多くの投稿は、より長いイテレータ構文for(std::vector<Type*>::const_iterator it = vec.begin(); it != vec.end(); it++)を使用した場合と同じです(詳細はfor(const auto &it : vec)を参照)。しかし、私は彼らが同じではないと言うthis postに来た。const auto&iteratorを

現在、forループの要素を使用した後、その要素を消去しようとしていますが、const auto &it : nodesstd::vector<txml::XMLElement*>::iteratorに変換する方法があるのでしょうか?問題の

コード:私はかなり確信して、私はただのconstポインタとしてstd::vector<txml2::XMLElement*>を書き換えることができますが、このコードは一瞬でデバッグ用ですので、したくない

std::vector<txml2::XMLElement *> nodes; 
//... 
for (const auto &it : nodes) 
{ 
    //...  
    nodes.erase(it); 
} 

答えて

4

ループの範囲に基づく範囲宣言を反復子に変換してから反復処理中に削除しようとするべきではありません。反復処理中にイテレータを調整することさえ危険です。アルゴリズムに依存する必要があります。

Erase-remove idomを使用してください。
remove_ifと一緒に使用できます。


nodes.erase(std::remove_if(nodes.begin(), nodes.end(), [](auto it){ 

    //decide if the element should be deleted 
    return true || false; 

    }), nodes.end()); 
は、現在の技術仕様で、 erase_ifです:

それは次のようになります。
これは、上記のように同じ行動のクリーンバージョンです:

std::erase_if(nodes,[](auto it){ 

    //decide if the element should be deleted 
    return true || false; 
}); 
+0

ありがとう、それは大きな助けでした。最終的に 'set_difference'を使用して終わりましたが、それは正しいパスで私を得ました。 – ZeroPhase

1

あなたはイテレータが、要素への参照を得ることはありません。 std::findを実行したい場合を除き、イテレータを取得するのはかなり難しいです。

ベクトルはいいですから、要素ごとにカウンタを増やして、イテレータを取得するにはnodes.begin() + counterを実行しますが、その点を捨てます。

また、forループを使用すると、ベクトルの終了後に反復することになるでイテレータを消去するには、このコードをテストすることができます。

#include <iostream> 
#include <vector> 

using namespace std; 

int main() { 
    vector<int> v = {0,1,2,3,4,5,6}; 

    for (int x : v) { 
     cout << x << endl; 

     if (x == 2) { 
      v.erase(v.begin() + 2); 
     } 
    } 
    return 0; 
} 

あなたはイテレータを使用したい場合は、単に彼らとループを行います加えて、あなたは1ミッドループを消去したい場合、あなたはthis answerに従わなければなりません:あなたは同じようにうまく機能autoイテレータの全種類を、指定する必要はありません

for (auto it = res.begin() ; it != res.end();) { 
    const auto &value = *it; 

    if (condition) { 
    it = res.erase(it); 
    } else { 
    ++it; 
    } 
} 

注意。