返回值优化
返回值优化(RVO)是一种C++编译优化技术,当函数需要返回一个对象实例时候,就会创建一个临时对象并通过复制构造函数将目标对象复制到临时对象,这里有复制构造函数和析构函数会被多余的调用到,有代价,而通过返回值优化,C++标准允许省略调用这些复制构造函数和析构函数,提高性能。
下列内容主要参考于下面这篇文章,欢迎关注支持原作者:
触发RVO优化
#include <iostream>
class A {
public:
A (){
std::cout << "A(): addr= " << this << std::endl;
}
A (const A&) {
std::cout << "A(const A&): addr= " << this << std::endl;
}
A& operator=(const A&) {
std::cout << "operator=(&&): addr= " << this << std::endl;
return *this;
}
// A (A&&) {
// std::cout << "A(A&&): addr= " << this << std::endl;
// }
// A& operator=(A&&) {
// std::cout << "operator=(A&&): addr=" << this << std::endl;
// return *this;
// }
~A() {
std::cout << "~A(): addr=" << this << std::endl;
};
};
//NRVO 在VSDebug模式下默认被关闭,Release模式下默认被打开
//A makeA () {
// A a;
// return a;
//}
A makeA () {
return A();
}
int main () {
A a = makeA();
return 0;
}
执行结果
关闭RVO优化
VS2019默认在debug情况下关闭了NRVO优化,在release下开启了NRVO优化;ROV优化在两种情况下均开启 。
通过编译选项 -fno-elide-constructors 关闭 RVO(这里使用的编译器是 g++),VS暂时没找到关闭RVO优化的选项,这里直接引用原作者的结论:关闭 RVO 重新编译运行,输出结果符合预期:
A(): addr= 0x7ffc7e2cec07
A(const A&): addr= 0x7ffc7e2cec37
~A(): addr=0x7ffc7e2cec07
A(const A&): addr= 0x7ffc7e2cec36
~A(): addr=0x7ffc7e2cec37
~A(): addr=0x7ffc7e2cec36
在使用VS关闭NRVO优化下,输出结果如下:
RVO优化限制场景
- 返回std::move(a) 会使RVO优化失效。
A makeA () {
A a
return std::move(a);
}
输出结果:
2. 调用点不是对象初始化,而是赋值。
A makeA () {
A a;
return a;
}
int main () {
A a;
a = makeA();
return 0;
}
3. 返回的局部对象存在分支判断。
A makeA (bool flag) {
A a1, a2;
if (flag) {
return a1;
} else {
return a2;
}
}
int main () {
int x;
A a = makeA(x);
return 0;
}