0

これは (VS2010 を使用して) コンパイラに依存するかどうかに関係なく、次の操作で予期される移動動作が呼び出されないのはなぜですか。

LargeObject x;
x = SomeFunc(x);

関数をペアとして定義しました

LargeObject SomeFunc(const LargeObject& ob)
{
    LargeObject newOb;
    // perform operation on new object using old object
    return newOb;
}

LargeObject SomeFunc(LargeObject&& ob)
{
    // change object directly...
    return std::move(ob);
}

私は明示的に書く必要があります

x = SomeFunc(std::move(x));

それを実現するために、私はそれが好きではありません...

編集: const-ref を使用する最初の関数は、次のようなことも行う必要があるためです。

LargeObject x;
LargeObject y = SomeFunc(x);
4

2 に答える 2

5

xは左辺値なので、次のようにします。

x = SomeFunc(x);

const右辺値参照は左辺値にバインドできないため、左辺値参照を受け入れるオーバーロードが選択されます。2 番目のオーバーロードを選択する場合は、x何らかの方法で右辺値に変換する必要があります。これが何をするかstd::moveです。

...そして私はそれが好きではありません...

オブジェクトを関数に渡すことが暗黙的にオブジェクトを移動することを意味する場合は、さらに気に入らないと思います!

移動が実行されるかどうかは、コンパイラにどのように指示するかによって異なります。まず第一に、一般的なケースでは、コンパイラだけではコードのセマンティック分析を実行して、 への呼び出し後に必要かどうかを判断しません (できません) 。xSomeFunc(x)

さらに、次の 2 つの命令が引数を渡すときに異なる動作を引き起こした場合、非常に奇妙になります。

SomeFunc(x);         // Does not move
x = SomeFunc(x);     // Moves!?
于 2013-03-05T09:44:00.060 に答える
1

コンパイラがここで move ctor を呼び出さなければならない理由はありません。Move-ctor は、パラメーターとして渡されたオブジェクトがもう使用されないことが保証されていますが、あなたの場合、 x はローカル変数であり、使用できます (ああ、オーバーロードできる次の代入操作で使用されます) 等。)。明示的に呼び出す場合:

x = SomeFunc(std::move(x));

さらに移動操作によって破損した x を使用するリスクがあります (コンパイラーは、結果を同じ変数に再度割り当てることを気にしません)。

試す:

LargeObject ReturnsLargeObject()
{
    LargeObject x;
    return x;
}

SomeFunc(ReturnsLargeObject());

この状況では、あなたの move ctor を呼び出す必要があります。

于 2013-03-05T09:44:00.637 に答える