反復中に std::set から要素を削除する: 実装への影響
要素を削除しながらセットを反復処理すると、操作として課題が発生する可能性があります。イテレータが無効になる可能性があります。この文脈で、次のような疑問が生じます: この動作は C 標準によって定義されていますか、それとも実装固有ですか?
実装の依存関係
C 標準 (23.1) による.2.8)、セットへの要素の挿入はイテレータやコンテナへの参照に影響を与えるべきではありませんが、要素の削除は無効化のみを行う必要があります。イテレータと削除された要素への参照。ただし、消去操作中の反復子の動作は明示的に指定されていないため、実装固有の決定に委ねられています。
GCC 実装
提供されているサンプル コードでは、次のように使用しています。 Ubuntu 10.04 上の GCC 4.3.3 では、反復中にセットから要素を削除しても反復子は無効になりませんでした。これは、GCC の実装がより緩和されたアプローチに従っており、消去後の反復子の継続使用を許可していることを示唆しています。
適合ソリューション
標準への準拠を保証するには、別のアプローチが必要です。が必要です。一般的な解決策の 1 つは、要素を消去する前にイテレータのコピーを作成することです。
for (auto it = numbers.begin(); it != numbers.end(); ) { if (*it % 2 == 0) { numbers.erase(it++); } else { ++it; } }
この場合、後置インクリメント (it ) は古い位置を Erase() 関数に渡しながら同時に、次の要素。ここでは、接頭辞の増分 (条件が false の場合) で発生する可能性のある二重増分の問題を回避するため、後置増分が推奨されます。
C 11 Update
With C 11 の登場により、より洗練されたソリューションが利用可能になりました。 Erase() 関数は、削除された最後の要素 (最後の要素が削除された場合は set::end) に続く要素への反復子を返すようになりました。これにより、より簡潔な実装が可能になります:
for (auto it = numbers.begin(); it != numbers.end(); ) { if (*it % 2 == 0) { it = numbers.erase(it); } else { ++it; } }
以上が反復中に `std::set` から要素を削除するのは C で定義された動作ですか、それとも実装固有ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。