【问题标题】:Why NRVO is not applied here?为什么这里没有应用 NRVO?
【发布时间】:2013-04-16 13:32:53
【问题描述】:

当我在 VS2010 中运行此代码时,未应用 NRVO。

#include <stdio.h>

class A
{
    public:

    A() { printf( "I am in constructor\n" ); }
    A(const A& a) { printf( "I am in copy constructor\n" ); }
    ~A() { printf( "I am in destructor\n" ); }
    int i;       
};

A f(int j)
{
    A a;
    if ( j )  return a;
    a.i = j;
    return a; 
}

int main()
{
    A a;
    a = f(5);
}

编辑:这与析构函数有关。当我注释掉它的行时,使用的是 NRVO。但这是为什么呢?

【问题讨论】:

  • 您使用的是什么级别的优化?另请注意,如果只有一个返回值,则应用 NRVO 会简单得多,在这种情况下,这很简单,替换为 if:if (!j) a.i = j; 则应用的机会会更高。
  • 看这里,msdn.microsoft.com/en-us/library/ms364057%28v=vs.80%29.aspx NRVO 有限制。你确定,你启用了优化?
  • @DavidRodríguez-dribeas 我尝试了所有优化选项,结果都是一样的。
  • @user1042389:您的示例与 kassak 链接中的“示例 5”非常相似,其中优化失败,因为析构函数使控制流过于复杂,编译器无法分析。同样在那个链接中,它说“这实际上是 Visual C++ 2005 未来需要改进的东西”——也许他们在 2010 年之前没有做好这一改进。
  • @MikeSeymour 但它是阻止优化的析构函数。知道为什么会这样吗?

标签: c++ visual-studio-2010 nrvo


【解决方案1】:

为什么这里没有应用 NRVO?

如果这纯粹是您的好奇心,并且您想知道 VC10 如何通过算法决定是否执行 NRVO,那么唯一能够可靠地回答这个问题的人是那些知道 VC10 内部工作原理的人——那些编写它的人.

据我所知,根据 C++11 标准,编译器被允许在这种情况下执行 NRVO,不这样做只是编译器的决定 - 不是因为任何有效性约束。根据第 12.8/31 段:

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

在具有类返回类型的函数的 return 语句中,当表达式是 具有相同 cv-unqualified 的非易失性自动对象(函数或 catch 子句参数除外) type 作为函数返回类型,可以通过构造省略复制/移动操作 自动对象直接转化为函数的返回值

[...]

但是,如果您希望能够强制您的编译器执行 NRVO,那么答案是“您不能”。 p>

是否应用 NRVO 完全由编译器自行决定。你不能指望它,也不能指望它被执行。据我所知,这是所谓的“as-if”规则的唯一例外。

也就是说,随着您提高优化级别,执行 NRVO 的机会也会增加。

【讨论】:

  • 我只是想知道为什么这里没有应用它。
  • @user1042389:好的。在这种情况下,很难得到答案。我可以说的是,C++ 标准确实允许 NRVO,所以答案不是“因为它是不允许的”。
【解决方案2】:

我不知道您在您的环境中看到了什么,但这在 GCC 中可以正常工作(例如 see here):

正常:

I am in constructor
I am in constructor
I am in destructor
I am in destructor

-fno-elide-constructors

I am in constructor
I am in constructor
I am in copy constructor
I am in destructor
I am in destructor
I am in destructor

【讨论】:

  • 我在 VS2010 中获得了发布版本中的第二个输出,即启用了优化。
猜你喜欢
  • 1970-01-01
  • 2018-01-05
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
相关资源
最近更新 更多