【问题标题】:Why does the returned value need to be the first declared local for NRVO?为什么返回值必须是 NRVO 的第一个声明的本地值?
【发布时间】:2014-11-20 16:52:04
【问题描述】:

我的理解是,要让编译器能够进行命名返回值优化 (NRVO),返回值必须在函数体中的任何其他值之前声明。我怀疑这可能是由于发生异常时堆栈展开的顺序,但我不确定。命名返回值必须是函数体中第一个声明的原因是什么?

class C{};
C f(){
    C ret; //NRVO possible
    return ret;
}
C g(){
    int i;
    C ret;  //NRVO not possible?
    return ret;
}

用例:

auto c = f();
auto c2 = g();

编辑: 感谢所有回答者帮助我理解这一点,我开始怀疑 Chandler Carruth 在此处的声明:http://www.youtube.com/watch?v=fHNmRkzxHWs 分钟 32:30 可能具有误导性和/或我只是误解了它。首先声明返回变量似乎并不重要。

【问题讨论】:

  • 可能有 一些 编译器会施加此限制,但总的来说,您的理解是有缺陷的——变量定义顺序不会启用/禁用 NRVO。
  • 你测试过这个假设吗?如果是这样,使用哪个编译器?
  • 这个outdated link 可能会有所帮助

标签: c++ optimization rvo


【解决方案1】:

关于复制省略,该标准对变量的声明/定义顺序没有任何要求。请注意,标准说“实现是允许”,而不是应该、应该等。我们可以看到clang and gcc 发生了复制省略,但MSVC 没有,进一步巩固了这一点是实现定义的优化。

§12.8/31 描述了复制省略:

[..] 这种复制/移动操作的省略,称为复制省略,在以下情况下是允许的(可以组合到 消除多个副本):

——在具有类返回类型的函数的返回语句中,当 表达式是非易失性自动对象的名称(其他 比函数或 catch 子句参数)具有相同的 cv-unqualified 类型作为函数返回类型,复制/移动 直接构造自动对象可以省略操作 进入函数的返回值

——[..]

【讨论】:

    猜你喜欢
    • 2013-08-03
    • 2013-09-03
    • 2018-03-18
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多