例如我有代码,如下面的
//g++ 5.4.0
#include <iostream>
struct data
{
int n;
data()
{
std::cout << "data()\n";
}
data(const data&)
{
std::cout << "data(const data&)\n";
}
data(data&&)
{
std::cout << "data(data&&)\n";
}
};
class container
{
data d;
public:
data getData()
{
return std::move(d);
}
};
int main()
{
container c;
data result = c.getData();
}
输出是:
data()
data(data&&)
我不明白它是如何运作的。我没有将返回类型声明为data&&
,但移动构造函数可以正常工作。是的,代码为std::move(d)
,但返回类型不是data&&
。那么它是怎样工作的?
答案 0 :(得分:4)
此答案在c++17中有所改变。
data getData()
{
return std::move(d);
}
此方法将d
移动到其返回值。
data x = foo.getData();
这个从x
的返回值构造getData
。但是,如果getData
返回prvalue(匹配的值类型),则C ++标准鼓励并允许此构造 elided 。 Elision意味着合并返回值<{1}}的标识和生存期。只存在一个对象,而不是两个。
这允许跳过副作用,比如移动构造函数中的print语句。
所以x
是移动的对象,并且该移动直接构造d
。
如果您更改x
以返回getData
,则现在data&&
内没有移动,但在构建getData
时,一个移动完成。
在c++17中,x
的返回值绝不是对象,它是prvalue,c++17中的prvalues更像是创建对象的指令。实际上,省略不再是可选的。
答案 1 :(得分:3)
如果返回类型设置为data
(如您的情况),则返回的对象是prvalue。
如果返回类型设置为data&&
,则返回的对象为xrvalue。
在任何一种情况下,返回的对象都是右值,并且将调用result
的移动构造函数。