std::vector::erase() における反復子の無効化について理解する
この説明では、次の場合の反復子の無効化のトピックを詳しく掘り下げます。 std::vector::erase() を呼び出します。以前の議論から知られているように、ベクトルから要素を消去すると、消去された要素の後にある反復子が無効になることが確立されています。ただし、次のような疑問が生じます: 消去された要素に位置するイテレータは依然として有効であると考えられますか?
消去された位置にあるイテレータは使用可能なままであるべきであるという直感的な理解にもかかわらず、正確な動作は必ずしも明確ではありません。この概念を説明するために、ベクトルから奇数の整数をすべて削除する次のコード スニペットを分析してみましょう:
<code class="cpp">typedef std::vector<int> vectype; vectype vec; for (int i = 0; i < 100; ++i) vec.push_back(i); vectype::iterator it = vec.begin(); while (it != vec.end()) { if (*it % 2 == 1) vec.erase(it); else ++it; }</code>
このコードは正常に実行されますが、ベスト プラクティスに違反しています。 C 標準によれば、erase() はパラメータとして指定されたイテレータ以降のすべてのイテレータを無効にします。この場合、消去された位置の反復子が無効になることを意味します。
ただし、erase() は、消去された要素の直後の要素、または vec.end を指す新しい反復子を都合よく返します。 () そのような要素が存在しない場合。この新しい反復子を利用すると、反復を安全に再開できます。
前述の奇数要素を削除する方法は効率的ではないことに注意することが重要です。要素が削除されるたびに、後続の要素をベクトル内で左にシフトする必要があるため、複雑さは O(n2) になります。このタスクは、O(n) で動作する消去/削除イディオムを使用すると、より効率的に実行できます。 is_odd() のような述語を作成することで、消去操作を改良できます:
<code class="cpp">bool is_odd(int x) { return (x % 2) == 1; } vec.erase(std::remove_if(vec.begin(), vec.end(), is_odd), vec.end());</code>
以上が## std::vector::erase() の消去された位置にある反復子はまだ有効ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。