首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按值返回与右值引用

按值返回与右值引用
EN

Stack Overflow用户
提问于 2018-07-07 15:27:38
回答 2查看 228关注 0票数 3

question about returning temporaries 上回复后,我注意到有第二个回复,略有不同。

它不是通过值返回,而是通过右值引用返回。您能解释一下这些方法之间的区别以及它们的风险在哪里吗?

代码语言:javascript
复制
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
    };
EN

回答 2

Stack Overflow用户

发布于 2018-07-07 23:42:16

一个主要区别是,如果返回右值引用,则当返回值绑定到引用时,临时值的生命周期不会延长。

例如,

代码语言:javascript
复制
Bar&& rb = Bar{}.doThings();
use(rb); // not safe if returning rvalue reference, while safe if returning by value
票数 3
EN

Stack Overflow用户

发布于 2018-07-08 00:59:01

我对此很感兴趣,所以我编写了一个小测试程序:

代码语言:javascript
复制
#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";
}

输出:

代码语言:javascript
复制
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()工作得很好(实际上,它返回一个指向对象本身的指针,所以不会涉及复制或临时操作)。

我肯定我错过了一些重要的东西,所以我很想听听人们对此的反应。当然,通过右值引用返回是有一定目的的,也许是在更复杂的场景中。谢谢。

Live demo

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51220975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档