拷貝構造函數調用的幾種情況:
- 當用類的一個對象去初始化該類的另一個對象(或引用)時系統自動調用拷貝構造函數實現拷貝賦值。
- 若函數的形參為類對象,調用函數時,實參賦值給形參,系統自動調用拷貝構造函數。(這里可有可能被編譯器優化)
- 當函數的返回值是類對象時,系統自動調用拷貝構造函數。(注意會有編譯器可能會進行優化,而觀察不到拷貝的發生)
舉例說明:
#include<ctime>
#include<cstdlib>
#include<iterator>
#include<algorithm>
#include<iostream>
#include<numeric>
using namespace std;
class A {
public:
A():data(0){}
A(const A& a){
data = a.data;
cout << "拷貝構造函數調用\n";
}
A& operator=(const A&a){
data = a.data;
cout << "調用賦值函數\n";
return *this;
}
int data;
};
void fun1(A a) {
return ;
}
A fun2() {
A a;
return a;
}
int main() {
A a;
A b(a); //用類的一個對象a去初始化另一個對象b
A c = a; //用類的一個對象a去初始化另一個對象c,注意這里是初始化,不是賦值
fun1(a); //形參為類對象,實參初始化形參,調用拷貝構造函數。
A d = fun2(); //函數返回一個類對象時, 這里可能會被編譯器優化,從而可能沒有調用拷貝構造
d = a; //d已經初始化過了,這里是賦值,調用賦值函數
return 0;
}
需要注意,在第三條:當函數的返回值是類對象時,系統自動調用拷貝構造函數。這里默認情況下一般會被編譯器優化,減少不必要的拷貝構造,所以,具體的返回值可能會因編譯器及編譯選項的不同而不同。使用g++編譯器,關閉優化g++ xxx.cpp -fno-elide-constructors
后執行結果如下:
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
調用賦值函數
默認情況下,優化后的結果如下:
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
調用賦值函數
編譯器具體是怎么優化的,一般編譯器會先看支不支持拷貝優化,如果不支持,再看有沒有定義移動構造函數,如果都沒有,就調用拷貝構造函數。更具體的細節可以參考移動語義及拷貝優化的內容。