返回值或右值引用
Return value or rvalue reference?
在Scott Meyer的新书中,他提出了一个右值引用限定符的示例用法,如下所示:
class Widget {
private:
DataType values;
public:
DataType& data() & { return values; }
DataType data() && { return std::move(values); } // why DataType?
};
因此:
auto values = makeWidget().data();
移动构造values
而不是复制构造它。
为什么符合 rvalue-ref 条件的data()
返回 DataType
而不是 DataType&&
? 在这种情况下,auto
仍然会推断出DataType
(尽管decltype(auto)
不会 - 但这不是更喜欢返回值而不是 ravlue 引用的唯一原因(。这个高投票的答案返回了一个右值参考,这对我来说在概念上更有意义。
DataType data() && { return std::move(values); } // why DataType?
auto values = makeWidget().data();
保存返回值的临时值将通过移动构造函数初始化,从 move(values)
复制初始化。
然后临时初始化values
,但由于makeWidget().data()
是一个右值(准确地说是prvalue(,移动构造函数再次被调用 - 临时作为其参数。
现在考虑复制省略:
当一个无名的临时的,不绑定到任何引用,将被移动 或复制到相同 CV 非限定类型的对象中, 省略复制/移动。当构造该临时时,它是 直接在存储中构建,否则它将被移动 或复制到。当无名临时是返回的参数时 语句,这种复制 elision 的变体称为 RVO,"返回值 优化"。
因此,第二步将(大概(被完全省略,只剩下一个 - 如果返回类型是右值引用,我们无论如何都会有。
返回右值引用的问题在于,如果我们编写
auto&& values = makeWidget().data();
values
将悬而未决,因为将 xvalue 绑定到引用不会延长任何内容的生命周期。当我们返回对象类型时,临时生存期会延长。
通过研究StackOverflow和技术博客终于弄明白了这一点,这里贡献了我的想法
class Widget {
private: DataType values;
public: DataType& data() & { return values; }
// return rvalue, okay, ref-qualifier necessary, since values not usable after move
DataType data() && { return std::move(values); }
// return rvalue reference, okay
DataType&& data_ref() && { return std::move(values); }
};
// note that auto is deduced to be Widget type
// okay, rvalue returned by function call moves construct w1
// if compiler implemented RVO copy elision, the move in move construct likely be elided
auto w1 = Widget().data();
// okay, rvalue reference returned by function call moves construct w2
auto w2 = Widget().data_ref();
// auto&& is a universal reference, deduced to be Widget&& rvalue reference
// dangling reference, bad. temporary copy is destroyed, so w3 is a dangling rvalue reference to values in the destroyed copy
auto&& w3 = Widget().data_ref();
如果auto&&
返回右值引用,它将被破坏。在这种特殊情况下,链接的答案被破坏了。
这里的核心问题是你可以重载左值或右值,但实际上有三个值类别你可能想知道 - 值,左值和右值。C++ 在调用成员函数时不区分 value 和 rvalue,因此您无法知道返回 rvalue 引用是否正确。无论你做出哪个决定,都很容易构建它不起作用的例子。
- 如何在不使用临时变量的情况下取消引用返回指针的函数的返回值?
- 对于具有引用返回类型的搜索算法,默认返回值应该是什么?
- C++对象引用返回不同的值
- 返回 std::tuple 中的引用和值
- 直接在 C++ 中将值分配给引用返回类型
- 是否未定义将对函数范围变量的引用作为值返回
- 可以通过常量引用返回默认参数的值吗?
- 我可以从取消引用"new"的返回值初始化引用吗
- C++ std::map 的返回值引用
- 按值与右值引用返回
- 非常量引用返回函数在常量值返回函数上用作 r 值
- 通过引用将函数传递给 TBB 任务时无法返回值
- C++复制按引用返回和按常量引用值返回
- 这安全吗?右值和引用返回值
- 引用返回值时出错
- 引用返回值和右值
- c++ const引用返回值的c#类比是什么?
- 在哪些情况下(const)引用返回值是不安全的?
- 将引用返回值赋给非引用变量
- c++ 11本地命名引用返回值(xvalue)