拷貝構造函數調用的幾種情況:當用類的一個對象去初始化該類的另一個對象(或引用)時系統自動調用拷貝構造函數實作拷貝指派。若函數的形參為類對象,調用函數時,實參指派給形參,系統自動調用拷貝構造函數。當函數的傳回值是類對象時,系統自動調用拷貝構造函數。
拷貝構造函數調用的幾種情況:
- 當用類的一個對象去初始化該類的另一個對象(或引用)時系統自動調用拷貝構造函數實作拷貝指派。
- 若函數的形參為類對象,調用函數時,實參指派給形參,系統自動調用拷貝構造函數。(這裡可有可能被編譯器優化)
- 當函數的傳回值是類對象時,系統自動調用拷貝構造函數。(注意會有編譯器可能會進行優化,而觀察不到拷貝的發生)
舉例說明:
#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
後執行結果如下:
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
調用指派函數
預設情況下,優化後的結果如下:
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
調用指派函數
編譯器具體是怎麼優化的,一般編譯器會先看支不支援拷貝優化,如果不支援,再看有沒有定義移動構造函數,如果都沒有,就調用拷貝構造函數。更具體的細節可以參考移動語義及拷貝優化的内容。