很多人应该都听过 RVO 或者返回值优化, 又或者构造优化,但是返回值优化的实现原理是什么样的, how?
下面将进行解密
分为两点解释:
-
编译器会对需要返回值优化的函数进行改造,从有返回值的类型, 变成多了一个额外参数类型,如下 A::makeA() -> A::makeA(void* ptr)
-
要明白构造函数到底做了什么:
<1>、申请内存, operator
<2>、在申请的内存进行初始化
<3>、返回内存起始地址<2>、<3> 的顺序可以颠倒
举例说明
A a = A::makeA()
//经过返回值优化有以下改变
1. void* y = operator new(sizeof(A));
2.A::makeA() —> A::makeA(void* y) // 在里面进行初始化
3. A* a = (A*)y;
下面具体测试用例
class A {
public:
A() {
cout << "A construct" << endl;
}
A(const A&) {
cout << "A copy construct" << endl;
}
void name() {
cout << "I am A" << endl;
}
static A makeA() {
A a;
cout << &a << endl;
cout << "make A()" << endl;
return a;
}
/*
* 编译器将 static A makeA() 签名优化成下面的有参形式void makeA(void* ptr);
* */
static void makeA(void* ptr) {
ptr = new (ptr) A;
cout << ptr << endl;
cout << "make A(ptr)" << endl;
return;
}
};
int main() {
auto x = A::makeA();
cout << &x << endl;
cout << "++++++++++++++++++++++++++++ " << endl;
// 模拟返回值优化
// 核心是吧 构造的时候的 分配内存和初始化分离
// 1 . operator new 分配内存
A* y = (A*)::operator new(sizeof (A));
// 2. 调用编译器优化后的函数, 对 y 进行初始化
A::makeA(y);
cout << y << endl;
y->name();
free(y);
y = nullptr;
}
1. 禁止返回值优化 g++ main.cpp -fno-elide-constructors
3. 默认返回值优化 g++ main.cpp
输出