std::vector では、テンプレート引数がデフォルトで構築可能である必要があることをいくつかの場所で読みました。今日、d デフォルト コンストラクターを持つクラスの 1 つで試してみましたがdelete
、驚いたことに (std::vector のデフォルト コンストラクターを使用して) 正常に動作しているようです。これは移植可能な動作ですか、それともこれは gcc の STL の実装の詳細ですか? vector がそのテンプレート引数をデフォルトで構築可能にする必要があると想定する必要がありますか?
4 に答える
C++11 でvector<T>
既定のコンストラクトブルを必要とするメンバーが 2 つあります。T
explicit vector(size_type n);
void resize(size_type sz);
他に何もしません。したがって、これらのシグネチャを使用する場合は、デフォルトの構築可能な型が必要です。それ以外の場合は必要ありません。
C++03 での要件は、コンテナーに格納される型がCopyConstructible
andであることAssignable
です (§23.1 コンテナー要件を参照)。ただし、C++11 ではこれらの要件が緩和され、コンテナーで実行される操作に適用される傾向があります。したがって、単純なデフォルトの構成には要件がありません (表 96、C++11 標準の §23.1 を参照)。
ベクトルをコピーしたり、要素を挿入したりするとすぐに、、、、、などのCopyInsertable
要件が満たされます。CopyAssignable
EmplaceConstructible
MoveInsertable
MoveAssignable
std::vector
要素の型がデフォルトで構築可能であることを無条件に要求するわけではありません。
(C++98、C++03)の元の仕様ではstd::vector
、その要素を内部的にデフォルト構築しようとさえしません。すべての新しい要素は、引数として「外部から」(呼び出しコードによって) 提供されたオブジェクトから常にコピー構築されます。これは、ベクターでデフォルトで構築された要素が必要になるたびに、それをデフォルトで構築し、コピーする「元の」要素として提供する必要があるのは、コードの側 (呼び出し元) であることを意味します。std::vector
たとえば、C++98 でこのようなことをすると、
std::vector<some_type> v(42);
v.resize(64);
それは実際に展開します
std::vector<some_type> v(42, some_type(), allocator_type());
v.resize(64, some_type());
デフォルトの引数メカニズムを介して。つまり、デフォルトで構築された「元の」要素は、ベクトルによって内部的に作成されるのではなく、呼び出しコードによってベクトルのコンストラクターに提供されます。
C++11 ではこれが変更され、内部std::vector
で要素のデフォルトの構築を実行するメソッドが追加されました。これは、ベクトル要素がデフォルトで構築可能であることを無条件に要求するわけではありません。これらの特定のメソッドを使用するには、デフォルトで構築可能な要素が必要であることを意味します。std::vector
まあ、テンプレートはある意味で弱く型付けされています。つまり、欠落している既定のコンストラクターは、おそらく内部的に使用されているメソッドをコードが呼び出すまで検出されません。これにより、コンパイル時エラーが発生します。
ただし、デフォルトのコンストラクターを内部で使用するメソッドに触れていない限り、「安全」です。ただし、どれが「安全な」サブセットかはわかりません。標準で定義されていないのではないかと思います。例: ベクトルのコピーでは が使用される場合resize
があり、これがデフォルトのコンストラクターを使用する場合があります。