20

次のコードを検討してください。

std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();

std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());

遭遇するほとんどすべての実装で、これは機能します。実装が何をするかは気にしません。規格が何を要求しているか知りたい。移動先vectorは元と同じ容量になりますか? それとも、アサートがトリガーされますか?

4

2 に答える 2

12

標準を見ると、移動コンストラクターからは何も必要ないように見えますが、@amaurea が言うように、移動コンストラクターがメモリの割り当てまたは割り当て解除を試みると、移動セマンティクスの目的が完全に無効になるため、容量が期待されますすべての実装で同じままにします。


23.2.1 一般的なコンテナ要件

表現

X u(a);
X u = a;

アサーション/メモの事前/事後条件

必須: TX に CopyInsertable です (以下を参照)。
役職:u == a


標準はそれを要求するだけですnewVec == vec。は容量を考慮していないためstd::vector::operator==newVec必ずしも と同じ容量である必要はありませんvec

于 2012-10-29T20:49:30.197 に答える
9

ムーブ コンストラクターの C++11 標準要件は次のstd::vectorとおりです (表 99 — アロケーター対応コンテナーの要件)。

X(rv)
X u(rv)
  • アロケータのムーブ構築は、例外によって終了してはならない
  • post:rvこの構築前と同じ要素を持つ必要があります。の値は、この構築前get_allocator()の の値と同じでなければなりません。rv.get_allocator()
  • 複雑さ: 定数

容量に関する要件/保証はありません。しかし、一定の複雑さは再割り当てを暗黙のうちに否定するという結論を下すことができます。また、再割り当て以外に容量を変更する論理的な理由は見当たりません。だから同じだろう。

別の観点からは、移動元のベクトルが空の場合、それを無視してそれ自体をデフォルトで構築することは完全に合法です。これは、要素ごとの構成を必要としないため、O(1) のままです。(この問題についてニコル・ボーラスに感謝します)。

また、実装により、関数hintのパラメーターを使用して容量をサイズに縮小できる可能性があります。std::allocator::allocate

pointer allocate(size_type, allocator<void>::const_pointer hint = 0);

の使用hintは指定されていませんが、実装が必要な場合に局所性を支援することを目的としています。したがって、一部の洗練されたソリューションでは、ベクトルストレージポインターを渡して、それをhint使用reallocして容量を縮小する可能性があります。

結論:標準では、移動時に容量を維持することは保証されていないようstd::vectorです。ストレージが縮小される可能性があります。

于 2012-10-29T21:11:44.453 に答える