- STL コンテナー要素には
noexcept
、コピー コンストラクターとコピー代入演算子が必要ですか? できれば参考までにお願いします。 - そうでない場合、複数挿入中 (例: fill insert中) に例外が発生したときの STL コンテナーの状態は何ですか。
変更の傍受/拒否を許可する汎用ラッパーを作成しようとすると、問題が発生します。私が思いついた実装は、すべてのコンテナー タイプに特化していない限り (実際にはオプションではありません)、基になるコンテナーのセマンティクスを変更する可能性があります。
たとえばstd::vector
、フィル インサートがあります。
void insert (iterator position, size_type n, const value_type& val);
これは、 CopyInsertableと CopyAssignable の両方value_type
である必要があります。値の型がDefaultConstructibleである必要はないことに注意してください。
編集 3 Stroustrup自身 (956 ページの表) は、複数要素の挿入がvector、deque、list、および map のすべてに対して強力な保証を持つことになっていることを示しています。完全な標準ライブラリ操作がアトミックに成功または失敗することを意味します。
編集 4ただし、保証は、関連する操作 (この場合はコピー コンストラクター) 自体が例外をスローしない場合にのみ適用されます。これはまさに私の問題です。
私が理解している限り、これにより 2 つの基本的な実装方法が残ります。
- 新しい要素と copy-assign のダミーエントリを作成します
val
。これは、コンテナー内の既存の要素をコピーすることによってダミー要素を作成できる場合、またはDefaultConstructiblevalue_type
である場合(必須ではありません) にのみ機能します。 - 要素をコンテナ内のそれぞれの場所に直接コピー構築します。これは多かれ少なかれ標準的な実装のようです。
編集2 :この用語は、言語ランタイム/標準によって未定義と考えるように人々に警告しているように見えるため、この未定義の動作とは呼びません。
どちらの実装も、コピー コンストラクターまたはコピー代入演算子のいずれかが例外を発生させると、コンテナーの内容が不明なままになるようです(つまり、例外の後にコンテナーが保持する要素が明確ではありません) 。
編集 1 : これは、メモリ リークや未定義の値など、C++ ランタイムに不適切な動作があると想定しているわけではないことに注意してください。ただし、コンテナの内容は多かれ少なかれ特定されていないようです。特に、コンテナーの内容は (一貫してはいますが) 完全に変更されている可能性があります。
例として、3 番目の (ハイブリッド) メソッドを考えてみましょう。
n
テンプレート オブジェクトのコピーのリストを作成しますval
。- このリストの要素をコピーしてターゲット コンテナーに割り当てます。
違いは、コピー コンストラクターが例外を発生させたときのコンテナーへの影響です。この場合、コピー コンストラクターがスローした場合、コンテナーの内容は変更されません (ただし、コピー代入演算子がスローした場合は未指定のコンテンツが発生します)。ポインターを使用する場合 (つまり、 を使用しない場合std::vector
) は、コピー代入を省略してポインターのみを再配置し、操作をアトミック wrt にすることができます。例外。
コンテナ要素については、noexcept
オブジェクトは を介して作成されますがallocator_traits<value_type>::construct(ptr, args)
、そうではなく、コンテナ要素にコピーコンストラクタ/コピー代入演算子noexcept
がほとんどあるという要件も見つかりません(たとえば、これが必要です)。noexcept
std::shared_ptr
std::unique_ptr
copy-construct および copy-assign の自動生成操作はnoexcept
、それ自体が例外を発生させる可能性のある操作を呼び出す必要がない限り、必要であることに注意してください。
これは私を混乱させ、何かを見逃したと確信していますが、私が間違っていることを証明するかもしれない標準の部分を理解することはできません.