关于“return std :: move(* this);”有什么不对吗?

时间:2012-10-17 19:31:26

标签: c++ c++11 move-semantics

我知道某个对象只是作为临时对象创建的(它是库中的私有成员对象)。有时,通过将成员函数链接在一起(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());

1 个答案:

答案 0 :(得分:3)

使用移动语义,您不希望(或需要)从函数返回r值引用... r值引用是指" capture"未命名的值或内存地址。当你从调用者的角度返回一个实际上是l值的对象的r值引用时,语义都是错误的,并且当其他人使用你的对象时你创造了不必要的惊喜的机会&# 39;方法。

换句话说,最好将代码定位如下:

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

并让TempObj::Member只返回一个l值引用。这使得移动变得明确,并且使用对象方法的人不会涉及任何惊喜。

最后,不,它在功能上或语义上与上一个例子不同。在那里,您实际上正在创建对象的临时副本,并且该副本将是一个r值对象(即,此场景中的一个未命名对象)...因为具有r值引用的假设是对象是一个unamed值或对象,因此它可以通过传递给它的函数进行无害修改,该函数采用r值引用参数。另一方面,如果您已将对象的副本传递给函数,则该函数无法修改原始函数。它只会修改引用的临时r值,当函数退出时,对象的临时r值副本将被销毁。