举例说明
#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 ctor
p.text::~text(); //default ctor
return ;
}
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 ctor
return ;
}
总结
RVO的使用,减少了返回值__tmp的构造和析构的成本。若直接返回一个将亡值(此处为匿名对象),那么还会减少一次匿名对象的创建和析构!
NRVO
N代表name,于上述RVO的区别在于,其会将RVO的优化结果1中的结果,进一步优化成优化结果2中的结果。
编译器支持情况
VS在debug模式下支持RVO,在release模式下支持NRVO。