C++笔记-编译优化:RVO、NRVO
C++编译器优化技术:RVO、NRVO和复制省略: https://www.cnblogs.com/kekec/p/11303391.html
C++中的RVO和NRVO:https://blog.csdn.net/yao_zou/article/details/50759301
详解RVO与NRVO(区别于网上常见的RVO) https://blog.csdn.net/virtual_func/article/details/48709617
RVO和NRVO的区别是什么?: https://www.zhihu.com/question/29511959
RVO和NRVO
RVO (return value optimization), 返回值优化,简称RVO,是编译器的一项优化技术,它涉及(功能是)消除为保存函数返回值而创建的临时对象。
NRVO (named return value optimization),NRVO的优化比RVO 的优化更进一步,直接将要初始化的对象替代掉返回的局部对象进行操作。
#include <stdio.h>
class Object {
public:
Object() { printf("%p construct\n", this); }
Object(const Object& cp) { printf("%p copy construct\n", this); }
~Object() { printf("%p destruct\n", this); }
};
Object getObjRVO() {
return Object(); // RVO
}
Object getObjNRVO() {
Object localObj;
return localObj; // NRVO
}
int main() {
printf("rvo:\n");
{ auto a = getObjRVO(); }
printf("nrvo:\n");
{ auto b = getObjNRVO(); }
return 0;
}
// https://www.zhihu.com/question/32237405/answer/55440484
编译:g++ test_rvo.cpp -o test
执行结果:
rvo:
0x7ffe558ff9de construct
0x7ffe558ff9de destruct
nrvo:
0x7ffe558ff9df construct
0x7ffe558ff9df destruct
增加编译选项 -fno-elide-constructors
编译:g++ test_rvo.cpp -o test -fno-elide-constructors
执行结果:
rvo:
0x7ffe3197775f construct // getObj 内部构造临时对象
0x7ffe3197778e copy construct // return时,调用复制构造函数构造返回值
0x7ffd9de82f8f destruct // 析构getObj内部的临时对象
0x7ffd9de82fbd copy construct // main函数内利用Object的拷贝构造函数构造对象a
0x7ffd9de82fbe destruct // 析构返回值
0x7ffd9de82fbd destruct // 析构对象a
nrvo:
0x7ffd9de82f8f construct
0x7ffd9de82fbf copy construct
0x7ffd9de82f8f destruct
0x7ffd9de82fbc copy construct
0x7ffd9de82fbf destruct
0x7ffd9de82fbc destruct
-fno-elide-constructors 编译选项释义:
The C++ standard allows an implementation to omit creating a temporary that is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases.
C++ 标准允许实现省略创建仅用于初始化相同类型的另一个对象的临时对象。 指定此选项会禁用该优化,并强制 g++ 在所有情况下调用复制构造函数。
增加转移构造函数
class Object {
public:
Object() { printf("%p construct\n", this); }
Object(const Object& cp) { printf("%p copy construct\n", this); }
Object(Object&& cp) { printf("%p move construct\n", this); }
~Object() { printf("%p destruct\n", this); }
};
编译:g++ test_rvo.cpp -o test -fno-elide-constructors
执行结果:
rvo:
0x7ffd42717a2f construct
0x7ffd42717a5e move construct
0x7ffd42717a2f destruct
0x7ffd42717a5d move construct
0x7ffd42717a5e destruct
0x7ffd42717a5d destruct
nrvo:
0x7ffd42717a2f construct
0x7ffd42717a5f move construct
0x7ffd42717a2f destruct
0x7ffd42717a5c move construct
0x7ffd42717a5f destruct
0x7ffd42717a5c destruct
发现没有再调用拷贝构造函数,而是调用的转移构造函数
RVO 和std::move对比
增加getObjNRVOMove方法
Object getObjNRVOMove() {
Object localObj;
return std::move(localObj); // NRVO
}
int main() {
printf("nrvo move:\n");
{ auto b = getObjNRVOMove(); }
return 0;
}
编译:g++ test_rvo.cpp -o test
执行结果:
nrvo move:
0x7ffc75a6a0ef construct
0x7ffc75a6a11d move construct
0x7ffc75a6a0ef destruct
0x7ffc75a6a11d destruct
可见RVO/ NRVO和std::move可同时生效