C++拷貝構造函數被調用的時機


拷貝構造函數調用的幾種情況:

  • 當用類的一個對象去初始化該類的另一個對象(或引用)時系統自動調用拷貝構造函數實現拷貝賦值。
  • 若函數的形參為類對象,調用函數時,實參賦值給形參,系統自動調用拷貝構造函數。(這里可有可能被編譯器優化)
  • 當函數的返回值是類對象時,系統自動調用拷貝構造函數。(注意會有編譯器可能會進行優化,而觀察不到拷貝的發生)

舉例說明:

#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后執行結果如下:

拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
調用賦值函數

默認情況下,優化后的結果如下:

拷貝構造函數調用
拷貝構造函數調用
拷貝構造函數調用
調用賦值函數

編譯器具體是怎么優化的,一般編譯器會先看支不支持拷貝優化,如果不支持,再看有沒有定義移動構造函數,如果都沒有,就調用拷貝構造函數。更具體的細節可以參考移動語義及拷貝優化的內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM