了解 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 的移动构造函数将被调用。

另请参阅:

此答案在 中更改。

data getData()
{
    return std::move(d);
}

此方法将 d 移动到其 return 值中。

data x = foo.getData();

这个从 getData 的 return 值构造 x。但是,如果 getData return 是纯右值(匹配的值类型),则 C++ 标准鼓励并允许 省略 构造。 Elision是指将return值和xidentitylifetime合并。只有一个对象存在,而不是两个。

这允许跳过副作用,例如移动构造函数中的打印语句。

所以d是移动的对象,移动直接构造x.

如果您将 getData 更改为 return data&&,现在在 getData 内没有移动,但是在构建 x 时在外部移动。

中,getData的return值从来不是一个对象,它是一个纯右值,中的纯右值更像是创建对象的指令。实际上省略不再是可选的。