6.拷贝对象时编译器的优化
优化场景1:隐式类型转换==>构造+拷贝构造–>直接构造
class A { public: A(int a = 10) :_a(a) { cout << "A(int a)" << endl; } ~A() { cout << "~A()" << endl; } private: int _a; }; int main() { A a1 = 1; return 0; }
这个场景的执行过程是:使用1构造了一个临时变量tmp,再使用这个tmp拷贝构造出a1,但是编译器在执行的时候会只能的优化成直接使用1构造a1。
优化场景2:匿名对象传参==>构造+拷贝构造–>直接构造
class A { public: A(int a = 10) :_a(a) { cout << "A(int a)" << endl; } ~A() { cout << "~A()" << endl; } A(const A& a) { _a = a._a; cout << "A(const A& a)" << endl; } private: int _a; }; void f1(A aa) {} int main() { cout << "场景一" << endl; A a1(1); f1(a1); cout << "场景二" << endl; f1(A(1)); return 0; }
场景一无法优化,因为两个变量并不能优化成一个,对于场景二,本来是使用1构造一个临时变量,然后传参,拷贝构造出aa,被优化成直接使用1构造aa。
优化场景3:传值返回==>拷贝构造+拷贝构造–>拷贝构造
class A { public: A(int a = 10) :_a(a) { cout << "A(int a)" << endl; } ~A() { cout << "~A()" << endl; } A(const A& a) { _a = a._a; cout << "A(const A& a)" << endl; } private: int _a; }; A f2() { A aa; return aa; } int main() { A ret = f2(); return 0; }
在传值返回的时候,会用aa拷贝构造出一个临时变量tmp,然后使用tmp拷贝构造出ret,优化成在调用结束之前使用aa直接拷贝构造出ret。
优化场景4:构造+拷贝构造+拷贝构造–>构造
class A { public: A(int a = 10) :_a(a) { cout << "A(int a)" << endl; } ~A() { cout << "~A()" << endl; } A(const A& a) { _a = a._a; cout << "A(const A& a)" << endl; } private: int _a; }; A f3() { return A(10); } int main() { A ret = f3(); return 0; }
这里触发了一个编译器的极致优化:使用10构造出一个临时变量tmp1,将这个临时变量拷贝构造出一个临时变量tmp2用于传值返回,再使用tmp2拷贝构造ret,最终优化成使用10构造ret。
注意:上述的所有优化都建立在一个步骤中,否则可能会引发一些不必要的风险
个临时变量tmp,然后使用tmp拷贝构造出ret,优化成在调用结束之前使用aa直接拷贝构造出ret。
优化场景4:构造+拷贝构造+拷贝构造–>构造
class A { public: A(int a = 10) :_a(a) { cout << "A(int a)" << endl; } ~A() { cout << "~A()" << endl; } A(const A& a) { _a = a._a; cout << "A(const A& a)" << endl; } private: int _a; }; A f3() { return A(10); } int main() { A ret = f3(); return 0; }
这里触发了一个编译器的极致优化:使用10构造出一个临时变量tmp1,将这个临时变量拷贝构造出一个临时变量tmp2用于传值返回,再使用tmp2拷贝构造ret,最终优化成使用10构造ret。
注意:上述的所有优化都建立在一个步骤中,否则可能会引发一些不必要的风险