在question about returning temporaries 上回复后,我注意到有第二个回复,略有不同。
它不是通过值返回,而是通过右值引用返回。您能解释一下这些方法之间的区别以及它们的风险在哪里吗?
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
};发布于 2018-07-07 23:42:16
一个主要区别是,如果返回右值引用,则当返回值绑定到引用时,临时值的生命周期不会延长。
例如,
Bar&& rb = Bar{}.doThings();
use(rb); // not safe if returning rvalue reference, while safe if returning by value发布于 2018-07-08 00:59:01
我对此很感兴趣,所以我编写了一个小测试程序:
#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 << "\n\n";
Bar&& bar_rvalue_ref = Bar ().doThings ();
std::cout << "bar_rvalue_ref refers to " << &bar_rvalue_ref.first << "\n\n";
}输出:
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()有什么用处,因为:
对于
*this移动,原则上,它会吃掉新构造的对象,因此返回的引用(仍然引用它)不会被依赖。正如@xskxzr已经指出的那样,在步骤1中创建的
然而,Bar& doThings()工作得很好(实际上,它返回一个指向对象本身的指针,所以不会涉及复制或临时操作)。
我肯定我错过了一些重要的东西,所以我很想听听人们对此的反应。当然,通过右值引用返回是有一定目的的,也许是在更复杂的场景中。谢谢。
https://stackoverflow.com/questions/51220975
复制相似问题