【问题标题】:return rvalue of temporary as value将临时的右值作为值返回
【发布时间】:2018-06-05 09:41:54
【问题描述】:

所以,我有以下课程:

class Foo {
public:
    Bar &&bar() {
        return std::move(_bar);
    }
private:
    Bar _bar;
}

我知道在以下情况下使用此类是有效的:

Bar bar;
{
    Foo foo;
    bar = foo.bar(); // bar is move-assigned, as foo is still in scope
}

现在,我想知道的情况是:如果我直接从一个方法返回 bar 而不是预先存储它会发生什么:

Bar testFunc() {
    Foo foo;
    return foo.bar();
}

Bar test = testFunc();
// is test now valid?

我认为这在理论上应该没问题,因为 testFunc 返回一个在 foo 被销毁之前从右值构造的值 - 但如果编译器应用返回值优化,情况仍然如此吗?

我想我有点困惑这到底是如何工作的......

【问题讨论】:

  • return foo.bar() 不是 RVO 的有效标准,所以是的,将从右值复制一份。

标签: c++ rvalue rvo


【解决方案1】:

现在测试有效吗?

只要移出的对象未被访问,代码就应该是有效的。

但是如果编译器适用,情况仍然如此 返回值优化?

Bar testFunc() {
    Foo foo;          // Bar is constructed here
    return foo.bar(); // prvalue is move-constructed and copy elided
}
Bar test = testFunc(); // default ctor + move ctor (one copy elision)

总共执行了一次复制删除。

移出成员似乎是一种代码味道。不知道具体用法很难判断,但也许:

Bar make_bar(const Foo& foo) {
    Bar bar;
    // init bar as needed
    return bar;
}

这样两个调用都会导致 RVO。

【讨论】:

  • 好的,在阅读了 c++17 中的值类别之后 - 将方法更改为 Bar Foo::bar() 会返回一个纯右值并使优化成为可能?还是该方法中的 return 语句(当前返回一个 xvalue)也必须返回一个纯右值?
  • @Felix,我更新了答案。我错了:testFunc() 会做 RVO。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-21
  • 1970-01-01
相关资源
最近更新 更多