了解 return 上的右值引用
Understanding rvalue reference on return
例如我有如下代码
//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&&)
我不明白它是如何工作的。我没有将 return 类型声明为 data&&
,但移动构造函数对结果工作正常。是的,代码是 std::move(d)
但 return 类型不是 data&&
。那么它是怎样工作的?
如果 return 类型设置为 data
(如您的情况),则 returned 对象是纯右值。
如果 return 类型设置为 data&&
,则 returned 对象是一个 xrvalue。
无论哪种情况,returned 对象都是右值,result
的移动构造函数将被调用。
另请参阅:
此答案在 c++17 中更改。
data getData()
{
return std::move(d);
}
此方法将 d
移动到其 return 值中。
data x = foo.getData();
这个从 getData
的 return 值构造 x
。但是,如果 getData
return 是纯右值(匹配的值类型),则 C++ 标准鼓励并允许 省略 构造。 Elision是指将return值和x
的identity和lifetime合并。只有一个对象存在,而不是两个。
这允许跳过副作用,例如移动构造函数中的打印语句。
所以d
是移动的对象,移动直接构造x
.
如果您将 getData
更改为 return data&&
,现在在 getData
内没有移动,但是在构建 x
时在外部移动。
在c++17中,getData
的return值从来不是一个对象,它是一个纯右值,c++17中的纯右值更像是创建对象的指令。实际上省略不再是可选的。
例如我有如下代码
//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&&)
我不明白它是如何工作的。我没有将 return 类型声明为 data&&
,但移动构造函数对结果工作正常。是的,代码是 std::move(d)
但 return 类型不是 data&&
。那么它是怎样工作的?
如果 return 类型设置为 data
(如您的情况),则 returned 对象是纯右值。
如果 return 类型设置为 data&&
,则 returned 对象是一个 xrvalue。
无论哪种情况,returned 对象都是右值,result
的移动构造函数将被调用。
另请参阅:
此答案在 c++17 中更改。
data getData()
{
return std::move(d);
}
此方法将 d
移动到其 return 值中。
data x = foo.getData();
这个从 getData
的 return 值构造 x
。但是,如果 getData
return 是纯右值(匹配的值类型),则 C++ 标准鼓励并允许 省略 构造。 Elision是指将return值和x
的identity和lifetime合并。只有一个对象存在,而不是两个。
这允许跳过副作用,例如移动构造函数中的打印语句。
所以d
是移动的对象,移动直接构造x
.
如果您将 getData
更改为 return data&&
,现在在 getData
内没有移动,但是在构建 x
时在外部移动。
在c++17中,getData
的return值从来不是一个对象,它是一个纯右值,c++17中的纯右值更像是创建对象的指令。实际上省略不再是可选的。