(N)RVO: (Named) Return Value Optimization
(具名)返回值优化
声明:本文中的RVO只是表示函数返回对象是非具名的。以及下文中一律以RVO表示具名或非具名返回值优化。
(N)RVO的适用场景
不得不返回类对象的情况下,由于作为返回值的类对象需要调用构造函数、拷贝构造函数、析构函数,带来的开销。这部分开销可以通过返回值优化机制来消除。(默认C++编译器是打开RVO的)
如何使用RVO机制来提高代码效率
通过使用函数的return 位置(或者在函数被调用位置用一个对象来替代)来消除局部临时对象。[^1]
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout<<this<<" constructor"<<endl;
}
A(const A &other)
{
cout<<this<<" cp contructor from "<<&other<<endl;
}
A & operator=(const A &other)
{
cout<<this<<" operator = "<<&other<<endl;
return *this;
}
~A()
{
cout<<this<<" destructor"<<endl;
}
};
示例一
A foo()
{
return A();
}
int main()
{
A a = foo(); //返回值优化RVO:利用return的位置;相当于使用a的内存来创建foo临时对象A()
return 0;
}
运行结果:
0x7ffe25e9ba58 constructor
0x7ffe25e9ba58 destructor
示例二
A foo()
{
A a;
return a;
}
int main()
{
A a = foo(); //返回值优化RVO:利用return的位置;相当于使用a的内存来创建foo临时对象A()
//foo(); //RVO依然有效
return 0;
}
运行结果:
0x7ffe15999168 constructor
0x7ffe15999168 destructor
示例三
A foo()
{
A a;
return a; //具名返回
//return A(); //不具名返回
}
int main()
{
A a;
a = foo(); //error
return 0;
}
运行结果:(具名返回和不具名返回的运行结果一样)
0x7ffeede2a268 constructor
0x7ffeede2a260 constructor
0x7ffeede2a268 operator = 0x7ffeede2a260
signal: illegal instruction (core dumped)
其中,0x7ffeede2a260应该是foo()返回的临时对象。
对于示例三的结果,我的理解是,通过赋值运算符接收函数返回的临时类对象时,没有返回值优化。即
接收栈对象的方式不同,会影响优化。
拓展
- 如果foo()是一段短小的、被频繁调用的函数,可以将其定义为inline函数来避免函数调用开销。
inline A foo()
{
...
}
参考:
[1] https://blog.csdn.net/qianqin_2014/article/details/51333388