2016-11-23 7 views
0

イレーズはイテレータを自動的に前方に移動させるので、複数のオカレンスを削除するには、これを避ける必要があるので、連続する要素を比較できます。だからこそ、私は通常の操作を行います。C++ 11:ベクトルからの複数のオカレンスを消去します。ベストプラクティスはどれですか?

auto i = vect.begin(); 
while (i!=vect.end()) 
    if (*i==someValue) 
     vect.erase(i); 
    else 
     ++i; 

しかし、私はまた、このように、forループでそれを行うことができれば、私は思っていた:--i部分は少し奇妙に見えるが、それは動作します

for (auto i=vec.begin(); i!=vec.end(); ++i) 
    if (*i==someValue){ 
     vec.erase(i); 
     --i; 
} 

。それは悪い習慣でしょうか?悪いコード?間違いを起こしやすい?それともどちらのオプションを使うのも正しいですか?

ありがとうございました。

+1

どちらも信頼できません。これを行う:https://stackoverflow.com/questions/3938838/erasing-from-a-stdvector-while-doing-a-for-each – Ryan

+0

なぜ彼らは信頼できないのですか?それが正しいのであれば、私はむしろ自分の選択肢に固執したいと思う。しかし、なぜイテレータが無効にならないようにするために 'i = vect.erase(i) 'を割り当てる必要があるかを除いて、なぜ正しくないのか分かりません。 –

答えて

4

使用削除、消去イディオム:コード上にO(N)の複雑さを有し、

とC++ 17からのデータ競合が存在していない場合には、並列に実行することができる

auto new_end = std::remove(v.begin(), v.end(), some_value); 
v.erase(new_end, v.end()); 

こと

template< class ExecutionPolicy, class ForwardIt, class T > 
ForwardIt remove(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, const T& value); 

またはparallelism TS

あなたのコードを使用しているためvector.modifiers#3

から問題がありますの

効果:でイテレータと参照を無効にしたり消去のポイント

後の標準はしかし、現実には、実装のほとんどが維持イテレータが


を無効にしていることを言いましたイテレータが古いノードを指しています。最後の要素または次の要素だった場合はendになります。コードはループするので、O(n )の複雑さを持ちますn回、データをシフトするにはnをもっと取得します。これは並行して実行することもできません。

+0

何らかの理由でコードが間違っていますか? –

+0

@VanessaLarralde標準の言葉では間違っている – Danh

+0

@Danh標準的な言葉だけでなく、ベクトル記憶は連続性が保証されているので、イテレータはベクトル記憶域への単純なメモリポインタとして実装されることが多い。要素の削除によって記憶域が縮小される – Dmitry

関連する問題