2010-12-07 5 views
1

のは、私はこのコードを持っているとしましょう:ベクトルが追加されたときに反復可能な参照を保持する方法

std::vector<Object*> objects; 
std::vector<Object*>::iterator iter; 
for (iter = objects.begin(); iter != objects.end(); iter++) { 
    if (condition) 
     objects.push_back(new Object()); 
} 

しかし、一backが発生したときに、iterがundereferenceableになります。 iterをリセットせずに、どうやって逆参照できますか?私がそれをリセットしなければならない場合、それを行う簡単な方法はありますか?

+0

このアイデアでは、反復処理中にオブジェクトを最後に追加すると、追加されるオブジェクトが増え反復が繰り返されるため、無限ループに陥る可能性がある終了することはありません(これは常に繰り返し処理する別のオブジェクトです)。 – MerickOWA

答えて

5

インデックスにアクセスすることをお勧めします。これにより、この問題は完全に排除されます。

0

数値インデックスを持つ古いforループになります。ループを実行する前にベクトルをリサイズしないでください。

また、生ポインタ? Srsly。

0

ベクトルがより多くのメモリを再割り当てする必要がある場合、イテレータは無効になります。

メモリの再割り当てを防ぐには、reserve()を使用して必要なすべてのメモリを事前に割り当てます(ベクトルを割り当てるときにこのサイズが分かっていることを前提とします)。

簡単な解決策は、メンバ(配列のインデックス)への間接参照を保つ方が簡単です。

1

あなたは絶対にこのためにイテレータを使用する必要がある場合:

std::vector<Object*> objects; 
std::vector<Object*> newObjects; 
std::vector<Object*>::iterator iter; 
for (iter = objects.begin(); iter != objects.end(); ++iter) 
{ 
    if (condition) 
    { 
     newObjects.push_back(new Object()); 
    } 
} 

std::copy(newObjects.begin(), newObjects.end(), back_inserter<vector<Object*> >(objects)); 
0

§23.1/ 11:特記のない限り

(どちらか 明示的または他の機能の面で機能 を定義することによって) コンテナメンバー関数を呼び出すか、 コンテナを引数として ライブラリ関数に渡しても、 イテレータを無効にしてはならないそのコンテナ内の オブジェクトの値を変更します。

ただし、明示的に指定されていないため、std :: vector :: push_backはどのイテレータも無効にします。

+0

私が行ったいくつかのテストでは、push_backが本当にイテレータを無効にできることを確認しています。 – Oswald

+0

おそらく、ベクトルがシーケンスであり、シーケンスsに対して、s.push_back(x)はs.insert(s.end()、x)として定義され、std :: vector :: insertはイテレータを無効にする。 – Oswald

0

他のほとんどの答えがすでに述べているように、この場合はインデックスを使用してベクターにアクセスする方がよいでしょう。

ただし、完全性のために:std::listイテレータにはこの「問題」はありません。したがってvectorの代わりにlistを使用することが考えられます。

関連する問題