ホームページ > バックエンド開発 > C++ > 反復中に `std::set` から要素を削除するのは C で定義された動作ですか、それとも実装固有ですか?

反復中に `std::set` から要素を削除するのは C で定義された動作ですか、それとも実装固有ですか?

Mary-Kate Olsen
リリース: 2024-12-04 08:30:14
オリジナル
629 人が閲覧しました

Is Deleting Elements from a `std::set` During Iteration Defined Behavior in C   or Implementation-Specific?

反復中に 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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート