【问题标题】:Does NRVO also apply to coroutines?NRVO 是否也适用于协程?
【发布时间】:2020-09-04 07:00:36
【问题描述】:

在以下示例中,NRVO(命名返回值优化) 按照this article 应用:

std::string f1()
{
    std::string str;

    return str; // NVRO applies here!
}

但是,请考虑:

task<std::string> f2()
{
    std::string str;

    co_return str; // Does NVRO also apply here?
}

【问题讨论】:

  • NRVO(命名返回值优化)根据这篇文章得到保证:”文章没有说这样的话。
  • 请注意,您的文章中不保证 NRVO。它甚至还有注意,尽管编译器有不同的优化能力,但并不能保证在 NRVO 示例代码之后立即应用上述优化
  • 我已经改写了这个问题。

标签: c++ optimization standards c++20 c++-coroutine


【解决方案1】:

我知道自 C++17 起 NRVO(命名返回值优化)是强制性的:

事实并非如此。 NRVO 仍然是一个优化。

未命名的返回值优化 (RVO) 是强制性的。

// Is NVRO also guaranteed here?

不,因为从不保证 NRVO。

【讨论】:

  • @xmllmx 请注意该引用中缺少“命名”。另请参阅示例,其中没有一个返回左值。另请参阅“非强制性省略副本”部分,其中特别提到了 NRVO。
  • 为什么是return str; NVRO 而不是co_return str;
  • co_return str; 不是 [NRVO]”是什么意思?
  • co_return str; 是否保证 move 而不是 copy str 到具体示例中的最终结果?
  • @xmllmx 我没有检查标准,但根据 cppreference 是的,str 会被移动。然而,这与复制省略或 NRVO 无关。
【解决方案2】:

为了完整起见,C++17 中的保证省略仅适用于直接从函数返回纯右值。返回一个命名变量只有在编译器喜欢的情况下才会被省略。

至于您问题的实质,co_return 的值从不受到复制省略的影响,无论是否保证。省略了 return 关键字的返回值键,并且协程不允许使用 return。他们使用co_return,即elision logic in the standard doesn't key off of。所以省略不适用。

之所以这样做是因为协程的工作方式。协程是一个函数,其中包含一个 Promise 对象。这个 promise 对象是你如何将协程的 co_return 值(和其他状态)传递给协程函数返回的“未来”对象。

省略在普通函数中起作用,因为调用约定要求调用者将返回值的存储传递给函数。因此,函数的实现可以选择仅在该存储中构建对象,而不是构建单独的堆栈对象并在return 上复制到其中。

在协程中,返回值存在于 Promise 中,因此这不可能真正发生。

【讨论】:

    【解决方案3】:

    只是因为答案看起来太长了。标准说声明co_return &lt;expr&gt;;相当于:

    P.return_value(<expr>);
    

    P 是协程的 promise 对象。从那我想你可以回答这个问题和许多其他问题。

    如果您正在寻找协程文档,请看这里:

    【讨论】:

      猜你喜欢
      • 2015-11-23
      • 2016-06-30
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 2011-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多