为什么这里不使用NRVO ?
Why NRVO is not applied here?
在VS2010中运行此代码时不应用NRVO。
#include <stdio.h>
class A
{
public:
A() { printf( "I am in constructorn" ); }
A(const A& a) { printf( "I am in copy constructorn" ); }
~A() { printf( "I am in destructorn" ); }
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 ?
如果这纯粹是你的好奇心,你想知道VC10算法是如何决定是否执行NRVO的,那么唯一能可靠地回答这个问题的人是那些知道VC10内部工作原理的人——那些写它的人。
就我所能告诉的,根据c++ 11标准,编译器允许在这种情况下执行NRVO,不这样做只是编译器的决定,而不是由于任何有效性约束。第12.8/31段:
[…复制/移动操作的省略,称为复制省略,在以下情况下是允许的(其中可以组合以消除多个副本):
- 在返回类型为的函数的返回语句中,当表达式是a的名称时具有相同cv-不合格的非易失性自动对象(函数或catch子句参数除外)类型作为函数返回类型,则可以通过构造来省略复制/移动操作自动对象直接转化为函数的返回值
[…]
然而,如果你期望你应该能够强迫编译器执行NRVO,那么答案是"你不能"。
是否应用NRVO完全由编译器自行决定。你不能指望它,你不能指望它不被执行。据我所知,这是所谓"as-if"规则的唯一例外。
也就是说,执行NRVO的机会随着提高优化级别而增加。
我不知道你在你的环境中看到了什么,但这在GCC中是预期的(例如见这里):
正常:I am in constructor
I am in constructor
I am in destructor
I am in destructor
With -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
相关文章:
- 警告处理为错误这里有什么问题
- 努力将整数转换为链表。不知道我在这里做错了什么
- 这里在 Linux 中具有"CreatePipe"和"CreateProcessW"功能吗?
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- File.cpp.o:OpenPose 标志 CMakeFiles/.. 的多重定义/main.cpp.o:首先在这里定
- 为什么thread_local变量在这里从未初始化?
- 为什么我必须在这里使用dynamic_cast
- C++ - 为什么这里需要'template'关键字?
- 这里的计数如何变成 5?
- 在这里,当我们比较 if(vc[i]==vc1[i]) 时,它是向量数组. 实际上比较的值是多少,
- 这里的 = 运算符有什么用法?
- 这里的字符串函数是什么意思
- 我正在尝试使用 while 循环从字符串中删除字母,直到没有字母。我在这里做错了什么?
- 为什么 C++20 中的 [[可能]] 属性在这里引发警告?
- 模板类是这里的最佳选择吗?如果是,我该怎么做?
- 为什么这里的大括号和括号初始化有区别?
- 我在这里正确传递参数了吗?
- 为什么gmp会在这里与"invalid next size"重新定位一起崩溃?
- 为什么这里不使用NRVO ?