C++類的設計中,如果某些函數沒有顯式定義,C++會自動生成,復制構造函數便是其中之一,其他的還有默認構造函數、賦值操作符、默認析構函數、地址操作符。一個類的復制構造函數的原型一般為: Class_name (const Class_name &);
一、何時調用復制構造函數
在新建一個對象並將其初始化為同類對象的時候,常常會調用復制構造函數,如:
Class_name A(B);
Class_name A = B ;
Class_name A = Class_name(B);
Class_name *p = new Class_name(A);// 用A初始化一個匿名對象,並將其地址賦予指針P
每當程序生成對象副本時,編譯器都會調用復制構造函數。具體地說,當函數按值傳遞對象或生成臨時對象時,編譯器都會調用復制構造函數。如當3個Vector對象相加時,編譯器會調用復制構造函數來生成臨時對象。
二、復制構造函數的淺復制
默認的復制構造函數是淺復制,即逐個復制非靜態成員數據的值。
(1)如果類成員是另一個類的對象,那麼將調用另一個對象的復制構造函數;
(2)靜態成員數據不被復制,因為它們屬於整個類,而不是一個對象。
(3)如果成員中含有含有指針P,那麼它的地址也會賦給新的對象中相應的P,這樣會導致兩個或多個變量指向同一個指針——比較危險的一件事。
三、復制構造函數的深復制
顯式地定義復制構造函數可以有效解決淺復制的弊端。下面以一個自定義的MyString類作為例子:
假若是使用默認的復制構造函數,則程序很容易崩潰,比如當你創建了對象A,用A初始化B(A和B的str指向同一個地址),然後銷毀A(此時A的str指向的內存已被收回),之後你如果想銷毀B,則可能使程序崩潰。
解決方法是顯式定義復制構造函數:
在函數中使用動態內存分配,在函數裡面也可以顯性改變靜態數據成員的值。與new相對應,在析構函數中使用delete關鍵字銷毀內存:
End.