按值与右值引用返回
Returning by value vs rvalue reference
在回答有关返回临时工的问题后,我注意到有第二个回复略有不同。
它不是按值返回,而是按右值引用返回。 您能解释一下这些方法之间的区别以及它们的风险在哪里吗?
struct Bar
{
Bar& doThings() & {return *this;}
// Returning rvalue reference
Bar&& doThings() && {return std::move(*this);}
// Alternative: Returning by value
//Bar doThings() && {return std::move(*this);}
std::unique_ptr<int> m_content; // A non-copyable type
};
一个主要区别是,如果返回右值引用,则当返回值绑定到引用时,临时的生存期将不会延长。
例如
Bar&& rb = Bar{}.doThings();
use(rb); // not safe if returning rvalue reference, while safe if returning by value
我对此很感兴趣,所以我敲了一个小测试程序:
#include <memory>
#include <iostream>
struct Bar
{
// Return by reference
Bar& doThings() & { return *this; }
// Return by rvalue reference
Bar&& doThings() && { std::cout << "in Bar&& doThings, this=" << (void *) this << "n"; return std::move (*this); }
~Bar () { std::cout << "Bar destroyed at " << (void *) this << "n"; }
int first;
std::unique_ptr<int> m_content; // Make Bar a non-copyable type
};
int main ()
{
std::cout << std::hex;
Bar bar;
std::cout << "bar is at " << &bar << "n";
Bar& bar_ref = bar.doThings ();
std::cout << "bar_ref refers to " << &bar_ref.first << "nn";
Bar&& bar_rvalue_ref = Bar ().doThings ();
std::cout << "bar_rvalue_ref refers to " << &bar_rvalue_ref.first << "nn";
}
输出:
bar is at 0x7ffdc10846f0
bar_ref refers to 0x7ffdc10846f0
in Bar&& doThings, this=0x7ffdc1084700
Bar destroyed at 0x7ffdc1084700
bar_rvalue_ref refers to 0x7ffdc1084700
Bar destroyed at 0x7ffdc10846f0
因此,这告诉我们,这两种形式的doThings()
都不会产生暂时性。 您也可以在Godbolt上验证这一点。
那么,看看所写的Bar
的实施,这给我们留下了什么? 好吧,我个人根本看不出Bar&& doThings()
有任何意义,因为:
- AFAICT,您只能在新构建的对象上调用它,因此无论如何它似乎没有什么意义。
- 因为它从
*this
移动,所以原则上它吃掉了新构造的对象,所以返回的引用(仍然引用它(是不依赖的。 - 正如@xskxzr已经指出的那样,在步骤 1 中创建的临时具有无限小的生存期。
然而,Bar& doThings()
工作得很好(并且实际上返回指向对象本身的指针,因此不会涉及复制或临时(。
我确定我错过了一些重要的东西,所以我很想听听人们对此的反应。 当然,通过右值引用返回是有一定目的的,也许在更复杂的情况下。 谢谢。
现场演示
相关文章:
- 寿命延长从函数返回引用
- 了解C++如何返回引用并绑定到引用
- 返回引用实例和非引用实例(return mystr & vs mystr)之间的区别是什么?
- 从类返回引用向量
- 使用unique_ptr并返回引用,或者我应该使用shared_ptr并在需要时制作副本
- 混淆C++从函数返回引用
- 两个相同的重载运算符[]一个返回引用
- 为什么向量的.at()成员函数返回引用而不是迭代器
- C++使用和返回引用
- 返回 T 引用的 Const 函子禁止赋值
- 返回引用是否也会延长其生存期?
- 如何返回引用,然后递增迭代器
- 如果使用返回引用的函数初始化"auto"var,为什么它不声明引用类型?
- 我是否需要将 ref 与 make_pair 一起使用才能返回引用?
- 在 vector::at 返回引用后进行更改
- 为什么PyImport_ImportModule返回引用计数为 3 而不是 1 的 PyObject*
- 超出返回引用的单一实例生存期
- Boost.Python 返回引用现有 c++ 对象的 python 对象
- C++ 运算符 += 重载返回引用
- 如何声明接受转发引用并返回引用或副本的函数模板