举例说明
#include <iostream>#include <cstring>using namespace std;class text{public:text() noexcept:_data(nullptr),_size(0){cout << "default ctor" << endl;}~text(){cout << "default dtor" << endl;_size = 0;if(_data!=nullptr){free(_data);_data = nullptr;}}text(char* p) noexcept:_data(p),_size(strlen(p)){cout << "customized ctor" << endl;}text(const text& rhs){_data = static_cast<char *>(malloc(rhs._size*sizeof(char)));_size = rhs._size;memcpy(this->_data, rhs._data, rhs._size);cout << "copy ctor" << endl;}text(text&& rhs) noexcept{_data = rhs._data;_size = rhs._size;rhs._data = nullptr;rhs._size = 0;cout << "move copy ctor" << endl;}text& operator=(const text& rhs){if (this != &rhs) {_data = static_cast<char*>(malloc(rhs._size*sizeof(char)));memcpy(this->_data, rhs._data, rhs._size);cout << "assign ctor" << endl;}return *this;}text& operator=(text&& rhs) noexcept{if (this != &rhs) {_data = rhs._data;_size = rhs._size;rhs._data = nullptr;rhs._size = 0;cout << "move assign ctor" << endl;}return *this;}private:char* _data;int _size;};text factory(){char* str = (char*)malloc(strlen("hello world!") * sizeof(char));memcpy(str, "hello world!", strlen("hello world!"));text p(str);return p;}text factory_fast(){char* str = (char*)malloc(strlen("hello world!") * sizeof(char));memcpy(str, "hello world!", strlen("hello world!"));return text(str);}int main(){text cur = factory();return 0;}
未使用RVO优化输出

- 调用用户定义构造函数生成临时变量b
- 通过移动拷贝构造函数创建右值__tmp,用作返回值
- 变量b析构
- 调用移动拷贝构造函数创建cur
- 右值__tmp析构
-
RVO优化结果1(包含临时变量创建)

调用用户定义构造函数生成临时变量b
- 通过移动拷贝构造创建cur
- 变量b析构
- cur析构
编译器会将代码优化至如下伪代码:
text factory_fast(const text &_result){char* str = (char*)malloc(strlen("hello world!") * sizeof(char));memcpy(str, "hello world!", strlen("hello world!"));//重要text p;p.text::text(str); //customized ctor_result.text::text(str); //move copy ctorp.text::~text(); //default ctorreturn ;}
RVO优化结果2(factory_fast)

编译器会将代码优化至如下伪代码
text factory_fast(const text &_result){char* str = (char*)malloc(strlen("hello world!") * sizeof(char));memcpy(str, "hello world!", strlen("hello world!"));//重要_result.text::text(str); //customized ctorreturn ;}
总结
RVO的使用,减少了返回值__tmp的构造和析构的成本。若直接返回一个将亡值(此处为匿名对象),那么还会减少一次匿名对象的创建和析构!
NRVO
N代表name,于上述RVO的区别在于,其会将RVO的优化结果1中的结果,进一步优化成优化结果2中的结果。
编译器支持情况
VS在debug模式下支持RVO,在release模式下支持NRVO。
