C++ “有什么不正确的地方吗?”;返回标准::移动(*此)&引用;?

C++ “有什么不正确的地方吗?”;返回标准::移动(*此)&引用;?,c++,c++11,move-semantics,C++,C++11,Move Semantics,我知道某个对象只是作为临时对象创建的(它是库中的私有成员对象)。有时,通过将成员函数链接在一起(TempObj().Init(“param”).Init(“其他参数”))进一步初始化该对象。我想使用该临时实例为另一个对象启用move构造,因此我想知道return std::move(*this)是否有任何错误 它的功能等同于此吗 struct TempObj { TempObj(TempObj &&other); TempObj Member() { /* do

我知道某个对象只是作为临时对象创建的(它是库中的私有成员对象)。有时,通过将成员函数链接在一起(
TempObj().Init(“param”).Init(“其他参数”)
)进一步初始化该对象。我想使用该临时实例为另一个对象启用move构造,因此我想知道
return std::move(*this)
是否有任何错误

它的功能等同于此吗

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

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

使用移动语义,您不希望(或不需要)从函数返回r值引用。。。r值引用用于“捕获”未命名的值或内存地址。从调用者的角度来看,当您返回一个对象的r值引用,而该对象实际上是一个l值时,语义都是错误的,并且当其他人使用您对象的方法时,您创造了出现不必要的意外的机会

换句话说,最好将代码定向为如下所示:

Foo foo(std::move(TempObj().Member()));
并让
TempObj::Member
只返回一个l值引用。这使移动变得明确,使用对象方法的人不会感到意外


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

使用移动语义,您不希望(或需要)从函数返回r值引用。。。r值引用用于“捕获”未命名的值或内存地址。从调用者的角度来看,当您返回一个对象的r值引用,而该对象实际上是一个l值时,语义都是错误的,并且当其他人使用您对象的方法时,您创造了出现不必要的意外的机会

换句话说,最好将代码定向为如下所示:

Foo foo(std::move(TempObj().Member()));
并让
TempObj::Member
只返回一个l值引用。这使移动变得明确,使用对象方法的人不会感到意外


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

关于最后一段,如果TempObj有一个移动构造函数怎么办?这会改变你写的吗?编辑:添加到问题中以使其完全清晰。另外,您是对的。虽然这可能不是非法的,但从呼叫方的角度来看,它肯定不是“正确的”。现在,我的真实世界
TempObj
等价物是图书馆的私人物品,但谁知道未来会带来什么。我只是想通过这样做来避免查找
TempObj().Member()
的所有实例并将它们包装在调用
std::move
中所需的工作,但我应该咬紧牙关,开始查找和替换。@moswald:“这会改变您编写的内容吗?”不会。
*这不是一个临时变量或超出范围的变量。因此,它不能绑定到
&
参数(例如在构造函数中)。这就是为什么需要在那里使用
std::move
来显式移动它。您不能从
*this
或任何类型的
*InserVariableName
隐式移动。正确的方法实际上是使用右值重载
TempObj Member()&&&&&&&&&&&…return std::move(*this);
以及左值重载
TempObj Member()const&(auto copy(*this);/*修改副本*/return copy;}
关于您的最后一段,如果TempObj有一个移动构造函数呢?这会改变您编写的内容吗?编辑:添加到问题中以使其完全清晰。另外,您是对的。虽然这可能不违法,但肯定不是“正确的”从调用方的角度来看。现在,我的真实世界
TempObj
等价物对库是私有的,但谁知道未来会发生什么。我只是试图避免查找
TempObj().Member()的所有实例所需的工作
并通过这样做将它们包装在对
std::move
的调用中,但我应该咬紧牙关,开始查找和替换。@moswald:“这会改变您编写的内容吗?”否。
*此
不是临时变量或超出范围的变量。因此,它不能绑定到
&
参数(例如在构造函数中)。这就是为什么您需要在那里使用
std::move
来显式移动它。您不能从
*this
或从任何类型的
*InserVariableName
隐式移动。正确的方法实际上是使用右值重载
TempObj Member()&&&{…return std::move(*this);
以及左值重载
TempObj Member()const&(自动复制(*this);/*修改副本*/return copy;}
请参见