3

コンテナーが連続していて、移動セマンティクスを同時にサポートするにはどうすればよいですか?

std::vector の例: 左辺値で std::move を使用して push_back() が呼び出された場合:

std::vector<MyClass> v;

MyClass obj;
MyClass obj2;

vt.push_back(std::move(obj));
vt.push_back(std::move(obj2));

obj と obj2 は、メモリ内で隣り合って割り当てられるとは限りません。ベクトルは連続したメモリに要素を持たなければならないので、この場合移動セマンティクスはどのように機能するでしょうか? obj2 をベクトル v の連続したメモリ領域 (obj の隣) にコピーする必要があるように思えます。そうしないと、連続性の要件が満たされません。しかし、それには移動ではなくコピーが必要です。上記とこれの違いは何ですか?:

MyClass obj;
MyClass obj2;

vt.push_back(std::move(obj));
vt.push_back(obj2);
4

2 に答える 2

2

移動セマンティクスについてもう少し読む必要があります:-)

オブジェクトを移動しても、オブジェクト自体のアドレスは変更されません。オブジェクトの別のインスタンスの移動コンストラクター(またはコンテキストに応じて代入演算子など)を呼び出すだけで、移動するインスタンスに渡されます。

この例では、ベクトルはMyClass内部ストレージ内に 2 つのオブジェクトを作成しますpush_back。ただし、最初のものでは、コピー コンストラクターを呼び出してobj(経由でMyClass const&) 渡す代わりに、移動コンストラクターを呼び出して右辺値参照 ( MyClass&&) を に渡しobjます。objオブジェクトのコンテンツをベクター内のコンテンツに移動するのは、そのコンストラクター次第です。

言い換えれば、オブジェクト自体ベクトルで作成され、移動されるのはそのコンテンツのみです (オブジェクトを「移動」することの意味は、タイプごとに異なる可能性があるため、実際の移動を行うのは移動コンストラクターの仕事です) )。

std::moveを使用しても、ムーブ コンストラクターは呼び出されない可能性があることに注意してください。たとえば、存在しないか、存在しない可能性がありますnoexcept(その場合std::vector、例外の安全性の保証に違反することなく、すべての状況でそれを使用することはできません)。 )。

于 2014-11-20T23:02:45.877 に答える