0

特定のオブジェクトが一時オブジェクトとしてのみ作成されることを知っています(これはライブラリ内のプライベートメンバーオブジェクトです)。場合によっては、そのオブジェクトは、メンバー関数をチェーン化することによってさらに初期化されます(TempObj().Init("param").Init("other param"))。その一時インスタンスを使用して別のオブジェクトの移動構築を有効にしたいので、について何か間違っていることがあるかどうか疑問に思いましたreturn std::move(*this)

struct TempObj
{
    TempObj &&Member() { /* do stuff */ return std::move(*this); }
};

struct Foo
{
    Foo(TempObj &&obj);
};

// typical usage:
Foo foo(TempObj().Member());

これと機能的に同等ですか?

struct TempObj
{
    TempObj(TempObj &&other);
    TempObj Member() { /* do stuff */ return *this; }
};

Foo foo(TempObj().Member());
4

1 に答える 1

3

移動セマンティクスでは、関数からr値参照を返す必要はありません(または必要ありません)。r値参照は、名前のない値またはメモリアドレスを「キャプチャ」するためにあります。呼び出し元の観点から実際にはl値であるオブジェクトへのr値参照を返す場合、セマンティクスはすべて間違っており、他の人がオブジェクトのメソッドを使用しているときに不必要な驚きが発生する機会が生じます。 。

つまり、コードを次のように配置することをお勧めします。

Foo foo(std::move(TempObj().Member()));

そして、TempObj::Member単にl値の参照を返します。これにより、動きが明確になり、オブジェクトのメソッドを使用している人に驚きはありません。

最後に、いいえ、それは機能的または意味的に最後の例と同等ではありません。そこで、実際にオブジェクトの一時的なコピーを作成しており、そのコピーはr値オブジェクト(つまり、このシナリオでは名前のないオブジェクト)になります... r値参照の前提は、オブジェクトが未処理の値またはオブジェクトであるため、r値参照引数を受け取る関数を渡すことで無害に変更できます。一方、オブジェクトのコピーを関数に渡した場合、関数は元のオブジェクトを変更できません。参照されている一時的なr値を変更するだけで、関数が終了すると、オブジェクトの一時的なr値のコピーが破棄されます。

于 2012-10-17T19:33:49.160 に答える