根据深度探索C++对象模型中的说法,如果类未定义拷贝构造且编译器也不合成拷贝构造,编译器不会对这个类施加NRV优化,即函数中声明的局部变量类实例,在return到类外部的时候,会进行一次拷贝,如果有拷贝构造,不管是合成的还是用户主动定义的,这个时候都不会拷贝,因此我写了如下测试代码,注:测试版本为g++ 13.2.0
class testmove{
public:
testmove(){
printf("%p construct\n", this);
}
~testmove(){
printf("%p destruct\n", this);
}
testmove(const testmove &){
}
};
testmove functestmove(){
testmove t;
printf("%p\n", &t);
return t;
}
int main(){
testmove t = functestmove();
printf("%p\n", &t);
return 0;
这时的打印为:
0x7ffeacdc7b63 construct
0x7ffeacdc7b63
0x7ffeacdc7b63
0x7ffeacdc7b63 destruct
这时有NRV优化,与预期相符,这时再去掉复制构造,其他的保持不变,此时类的定义更新为
class testmove{
public:
testmove(){
printf("%p construct\n", this);
}
~testmove(){
printf("%p destruct\n", this);
}
// testmove(const testmove &){
// }
};
这时的输出为
0x7fff9f15c023 construct
0x7fff9f15c023
0x7fff9f15c023
0x7fff9f15c023 destruct
从输出来看是有NRV优化的,与学习的理论冲突了,检查类的实现发现没有成员变量,没有继承,没有虚函数,也没有虚继承,不应该合成复制构造函数,将构造和析构都去掉试试,此时的类testmove为空类,此时运行程序发现输出为:
0x7ffe3e5f1dbf
0x7ffe3e5f1e03
也就是说将构造和析构都去掉之后没有NRV优化,再将构造函数加上试试,结果还是一样,没有NRV优化,加上析构函数,此时的输出如下
0x7ffe578a38b0 construct
0x7ffe578a38b0
0x7ffe578a38b0
0x7ffe578a38b0 destruct
此时是有NRV优化的,将析构函数注释,加上复制构造函数,输出如下:
0x7fff9a8c9f60 construct
0x7fff9a8c9f60
0x7fff9a8c9f60
也有NRV优化,至此得出以下结论:有析构函数或复制构造函数会施加NRV优化