返回值还是右值参考?

时间:2014-12-08 22:33:02

标签: c++ c++11 rvalue-reference

在Scott Meyer的新书中,他提出了rvalue引用限定符的示例用法,如下所示:

class Widget {
private:
    DataType values;

public:
    DataType& data() &  { return values; } 
    DataType  data() && { return std::move(values); } // why DataType?
};

那样:

auto values = makeWidget().data();

move-constructs values而不是复制构造它。

为什么rvalue-ref-qualified data()会返回DataType而不是DataType&&?在这种情况下,auto仍然会推断DataType(尽管decltype(auto)不会 - 但这不是唯一的理由更喜欢返回值而不是ravlue ref)。 This高度投票的回答会返回一个右值ref,这对我来说在概念上更有意义。

2 个答案:

答案 0 :(得分:7)

DataType data() && { return std::move(values); } // why DataType?

auto values = makeWidget().data();

保存返回值的临时值将通过move-constructor初始化,从move(values)进行复制初始化。

然后临时初始化values,但由于makeWidget().data()是一个rvalue(准确的prvalue),所以再次调用move-constructor - 将temporary作为其参数。

现在考虑copy-elision

  

当无名的临时,未绑定任何引用时,将被移动   或者复制到同一个cv-unqualified类型的对象中   复制/移动被省略。当构建临时建筑时,它就是   直接在存储器中构造,否则它将被移动   或复制到。当无名临时是返回的参数时   声明,复制省略的这种变体称为RVO,"返回值   优化"

所以第二步将(大概)完全省略,只留下一个 - 我们原本应该拥有的那个,返回类型是右值参考。

返回右值引用的问题是,如果我们写

auto&& values = makeWidget().data();

values将悬空,因为将xvalue绑定到引用并不会延长任何生命周期。当我们返回对象类型时,临时寿命会延长。

答案 1 :(得分:-4)

如果返回右值引用,

auto&&将被破坏。在这种特殊情况下,链接的答案被打破了。

这里的核心问题是你可以在左值或右值上重载,但实际上你可能想知道三个值类别 - 值,左值和右值。调用成员函数时,C ++不区分值和右值,因此您无法知道返回右值引用是否正确。无论你做出哪个决定,都可以很容易地构建不起作用的例子。