2012-02-10 1 views
0

C++には、forループ内で要素を追加できるデータ構造はありますか?イテレータを無効にせずに要素を挿入できる標準コンテナはありますか?

(それは私がこれまで試したものですので、私は例としてlistを使用。)

list<Elem> elems; 
// fill elems with some Elems; 

for(list<Elem>::iterator it=elems.begin(); it!=elems.end();) { 

    // ... 

    if(condition) 
     it = elems.erase(it); 
    else { 
     Elem elem; 
     it = elems.push_back(elem); 
    } 
} 

PS:これはDeleting elements from a vector

+0

これを行わないでください。新しいコンテナを作成し、元のコンテナと置き換えます。 –

+0

@KarlKnechtel、あなたがそれについて詳しく説明してくれれば、それは良い答えになると思います。これは、既存の回答がまだカバーしていないアプローチです。 –

答えて

1

へのフォローアップの質問ですはい、listができますあなたはこれを行うには..私は他の答えで私のコメントで言ったように...

+0

どうすればいいですか? 'it = elems.push_back(elem);'は動作できません(戻り値は無効です)。 – Ben

+0

最後に追加したい場合は、 'push_back()'を呼び出すだけです。現在の位置に挿入したい場合は、 'insert(it、value);'を呼びます。 ... – Nim

+0

これは、 'it = elems.insert(elem)'を実行すると、私はうまくいくはずです。 – Ben

3

This answer on StackOverflowは、すべての標準的な容器の動作の良い要約を与える。挿入または消去にイテレータを無効にしません

コンテナはlistsetmultisetmap、およびmultimapです。もちろん、イテレータは消去されません。

0

イテレータを無効にせずに挿入をサポートするseveral containersがあります。あなたのコードでは、削除ケースが正しいと思いますが、私はあなたが挿入ケースを熟考していると信じています。これを試してみてください:

else { 
    Elem elem; 
    elems.push_back(elems); 
    ++it; 
} 

あなたが与えられた例でlistを使用しているので、あなたはpush_back呼び出しがitを無効にしません知っています。したがって、単に次の要素に到達するまでインクリメントすることができます。 removing elementsのときは、存在しなくなった場所を指すイテレータをインクリメントできないため、注意する必要があります。

1

リクエストごとにこれを書いてください。

PS:これは

ベクターから削除する要素のフォローアップの質問です

これは質問のあなたのラインで厄介なパターンです。

真剣に、あなたが反復処理中にコンテナを変更すると、悪いジュジュです。正しいことは難しい。それはしばしばパフォーマンスの面であなたを救うものではありません。 (あなたのニーズにきちんと合った標準的なライブラリアルゴリズムがある限られた場合を除いて)簡単に表現することはほとんどありません。それが間違っていると、パフォーマンスが非常に高くなる可能性があります。あなたが間違っていると、プログラムの正確さの面で非常にコストがかかる可能性があります。これは他の何よりも重要です。

スレッディングが関与している場合は、指数関数的に悪化します。 Javaには、専用の例外タイプがあります。これは、これを試みるときに間違っている可能性のある特定の事柄に対して特に役立ちます。 C++では、あなたはとても幸運ではありません。類似の問題が検出されない可能性があります。

最終結果を生成するコードを書き、元のコンテナを置き換えます。これを本当に減速させることができるのは、「インスタンスはコピーするのに費用がかかります」ということだけです。その場合、問題を処理するためにインダイレクションのレイヤーを使用している必要があります。

list<Elem> original; 
// fill elems with some Elems; 
list<Elem> modified; 
for (
    list<Elem>::iterator it = original.begin(), end = original.end(); 
    it != end; ++it 
) { 
    if (something()) { 
     modified.push_back(*it); 
    } else if (something_else()) { 
     modified.push_back(Elem()); // for example 
    } 
    // else, 'erase' the element by just not putting anything into 'modified' 
    // Or we could do whatever other combination of things, 
    // maybe insert more than one 
} 
std::swap(original, modified); 
関連する問題