2

の動作についてはまだ混乱していますstd::vector::resize()。次のコードを検討してください ( std::vector<type> の型要件も参照してください) 。

struct A {
  A() : X(0) { std::cerr<<" A::A(); this="<<this<<'\n'; }
  A(A const&) { assert(0); }  // is required but doesn't fire in vector::resize
  int X;
};

int main()
{
  std::vector<A> a;
  a.resize(4);        // would not compile without A::A(A const&) or A::A(A&&)
}

A::A(A const&)またはがないA::A(A&&)と、 の行a.resize(4);はコンパイルされません。ただし、そのコンストラクターは決して呼び出されassert(0)ません: は起動しません! 誰かが私にそれを説明できますか?

allocator_traits<>私の解釈では、これらのコンストラクターのいずれかの存在は(used by )のテンプレート マジックによって必要とされますstd::vector::resize()が、実際には呼び出されません。ただし、メソッドを呼び出していないのに、なぜメソッドの存在が必要になるのでしょうか?

4

3 に答える 3

4

標準の最新版 ( n3376 ) は次のように述べています。

12 - の場合、デフォルトで挿入された要素をシーケンスsize() < szに追加します。 13 - 必須:である必要があります。sz - size()
TMoveInsertableDefaultInsertable*this

つまりMoveInsertable、発生する可能性のある再割り当てにDefaultInsertableは が必要ですが、実際の追加には が必要です。したがって、コピーまたは移動コンストラクターは、ベクターに既に要素が含まれており、再割り当てが必要な場合にのみ起動します。

実際、次のように書くと:

std::vector<A> a;
a.resize(1);
assert(!a.empty() && a.capacity() < 4);
a.resize(4);

次に、のコピーまたは移動コンストラクターAが呼び出され、アサートがトリガーされます。

于 2012-09-04T08:50:10.680 に答える
3

ベクトルを作成するにresizeは、新しいサイズで必要な要素を保持するのに十分なスペースがベクトルにない場合、既存の要素を新しく割り当てられたメモリのチャンクに配置する必要があります。これは、それらをコピー構築することによって行われます。したがって、ベクターのサイズを変更するには、コピー コンストラクターが必要です。この場合、既存の要素がないため、コピー コンストラクターは呼び出されません。しかし、それはまだ存在している必要があります。

于 2012-09-04T08:48:40.020 に答える
0

あなたの例では、 vector::resize() メソッドを呼び出すと、コピー コンストラクターの代わりにコンストラクターが呼び出されます。そのため、アサートがトリガーされていません。

コピー コンストラクター (および定義および宣言していないムーブ コンストラクター) が必要な理由は、テンプレートの型がコピー コンストラクターおよびムーブ コンストラクターである必要があるためです。[container.requirements.general]/15 は、コンテナーのタイプの要件を定義します。

— T is DefaultInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p);
— An element of X is default-inserted if it is initialized by evaluation of the expression allocator_traits<A>::construct(m, p);
where p is the address of the uninitialized storage for the element allocated within X.
— T is CopyInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p, v);
— T is MoveInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p, rv);
— T is EmplaceConstructible into X from args , for zero or more arguments args, means that the following expression is well-formed: allocator_traits<A>::construct(m, p, args);
— T is Erasable from X means that the following expression is well-formed: allocator_traits<A>::destroy(m, p);
于 2012-09-04T08:50:34.300 に答える