[前言]
现代编译器为了尽可能的提高程序的效率,在保证程序运行正确的情况下会进行一些优化。
这些优化体现在尽可能的省略一些不必要的拷贝(C++传参和传返回值的时候都会有拷贝)
不过到底怎么实现优化,优化的程度又是怎么样的,每一个编译器都不尽相同
这里我们就简单了解一下,在对象拷贝的时候会发生一些优化即可
之前我们在类和对象(下)里面聊类型转换的时候有提高一种优化,就是在隐式类型转换时,连续构造和拷贝构造会优化为直接构造
class A
{
public:
A(int a = 0) //构造函数
:_a1(a)
{
cout << "调用构造函数" << endl;
}
A(const A& aa) //构造函数重载
:_a1(aa._a1)
{
cout << "调用构造函数(类)" << endl;
}
A& operator=(const A& aa) //运算符重载
{
cout << "调用运算符重载" << endl;
if (this != &aa)
{
_a1 = aa._a1;
}
return *this;
}
~A() // 析构函数
{
cout << "调用析构函数" << endl;
}
private:
int _a1 = 1;
};
void f1(A aa)
{}
A f2()
{
A aa;
return aa;
}
int main()
{
// 传值传参
A aa1;
f1(aa1);
cout << endl; //传值传参是不存在优化的
// 隐式类型转换
f1(1); //连续构造+拷⻉构造->优化为直接构造
cout << endl;
// ⼀个表达式中,连续构造+拷⻉构造->优化为⼀个构造
f1(A(2)); //传一个匿名对象,传值传参一定会拷贝构造
cout << endl;
// 传值返回
f2();
cout << endl;
// 返回时⼀个表达式中,连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造
A aa2 = f2();
cout << endl;
// ⼀个表达式中,连续拷⻉构造+赋值重载->⽆法优化
aa1 = f2(); //这一步就不是定义了,而是赋值
cout << endl;
return 0;
}
以上代码,稍微理解即可,毕竟光看代码不容易去想象内部逻辑
所以接下来嘞,用画图来给大家解释以下,
我用上面代码中的某一个例子来具体说明了在不同编译器下,优化的具体情况
针对VS2022,为什么说可以理解为aa2优化为了aa的别名呢?
因为在VS2022中,我们通过打印aa和aa2的地址,可以发现它们二者的地址是相同的!这就不得不感叹一下编译器开发人员无比强大的编码水平了
ok,聊到这,相信大家对这个拷贝的优化应该是心里有点感觉了,当然这也就够用啦
那我们下一篇再见面喽~~