1.什麼是拷貝建構函式:
ca(const ca& c)
就是我們自定義的拷貝建構函式。可見,拷貝建構函式是一種特殊的建構函式,函式的名稱必須和類名稱一致,它的唯一的乙個引數是本型別的乙個引用變數,該引數是
const
型別,不可變的。例如:類
x的拷貝建構函式的形式為
x(x& x)
。當用乙個已初始化過了的自定義類型別物件去初始化另乙個新構造的物件的時候,拷貝建構函式就會被自動呼叫。也就是說,當類的物件需要拷貝時,拷貝建構函式將會被呼叫。以下情況都會呼叫拷貝建構函式:
①程式中需要新建立乙個物件,並用另乙個同類的物件對它初始化,如前面介紹的那樣。 ②
當函式的引數為類的物件時。在呼叫函式時需要將實參物件完整地傳遞給形參,也就是需要建立乙個實參的拷貝,這就是按實參複製乙個形參,系統是通過呼叫複製建構函式來實現的,這樣能保證形參具有和實參完全相同的值。 ③
函式的返回值是類的物件。在函式呼叫完畢將返回值帶回函式呼叫處時。此時需要將函式中的物件複製乙個臨時物件並傳給該函式的呼叫處。如
box f( )//函式f
的型別為
box類型別
int main( )
如果在類中沒有顯式地宣告乙個拷貝建構函式,那麼,編譯器將會自動生成乙個預設的拷貝建構函式,該建構函式完成物件之間的位拷貝。位拷貝又稱淺拷貝,後面將進行說明。
自定義拷貝建構函式是一種良好的程式設計風格,它可以阻止編譯器形成預設的拷貝建構函式,提高原始碼效率。
淺拷貝和深拷貝
在某些狀況下,類內成員變數需要動態開闢堆記憶體,如果實行位拷貝,也就是把物件裡的值完全複製給另乙個物件,如
a=b。這時,如果
b中有乙個成員變數指標已經申請了記憶體,那
a中的那個成員變數也指向同一塊記憶體。這就出現了問題:當
b把記憶體釋放了(如:析構),這時
a內的指標就是野指標了,出現執行錯誤。
深拷貝和淺拷貝可以簡單理解為:如果乙個類擁有資源,當這個類的物件發生複製過程的時候,資源重新分配,這個過程就是深拷貝,反之,沒有重新分配資源,就是淺拷貝。
2.c++拷貝建構函式的幾個細節
1)以下函式哪個是拷貝建構函式
,為什麼?
1.x::x( const x&);
2.x::x(x);
3.x::x(x&, int a=1);
4.x::x(x&, int a=1, b=2);
解答:1)
對於乙個類
x,如果乙個建構函式的第乙個引數是下列之一
:a) x&
b) const x&
c) volatile x&
d) const volatile x&
且沒有其他引數或其他引數都有預設值
,那麼這個函式是拷貝建構函式.
1.x::x( const x&); //是拷貝建構函式
2.x::x(x&, int =1); //是拷貝建構函式
2)乙個類中可以存在多於乙個的拷貝建構函式嗎?
解答:類中可以存在超過乙個拷貝建構函式,
1.classx ;
注意,如果乙個類中只存在乙個引數為x&的拷貝建構函式,那麼就不能使用const x或volatile x的物件實行拷貝初始化.
1.classx ;
6.
7.constx cx;
8.x x = cx; // error
如果乙個類中沒有定義拷貝建構函式,那麼編譯器會自動產生乙個預設的拷貝建構函式.
這個預設的引數可能為x::x(const x&)或x::x(x&),由編譯器根據上下文決定選擇哪乙個.
預設拷貝建構函式的行為如下:
預設的拷貝建構函式執行的順序與其他使用者定義的建構函式相同
,執行先父類後子類的構造
.拷貝建構函式對類中每乙個資料成員執行成員拷貝
(memberwise copy)
的動作.
a)如果資料成員為某乙個類的例項
,那麼呼叫此類的拷貝建構函式.b)
如果資料成員是乙個陣列
,對陣列的每乙個執行按位拷貝
. c)
如果資料成員是乙個數量,如
int,double,
那麼呼叫系統內建的賦值運算子對其進行賦值.
3)拷貝建構函式不能由成員函式模版生成
.
structx ;
原因很簡單
, 成員函式模版並不改變語言的規則
,而語言的規則說
,如果程式需要乙個拷貝建構函式而你沒有宣告它
,那麼編譯器會為你自動生成乙個
. 所以成員函式模版並不會阻止編譯器生成拷貝建構函式
, 賦值運算子過載也遵循同樣的規則
3.拷貝建構函式與賦值函式的異同:
1) 拷貝構造,是乙個的物件來初始化一片記憶體區域,這片記憶體區域就是你的新物件的記憶體區域賦值運算,對於乙個已經被初始化的物件來進行
operator=操作
classa;
aa;ab=a;//
拷貝構造函式呼叫
//或
ab(a);//
拷貝構造函式呼叫
///aa;
ab;b =a;//
賦值運算子呼叫
你只需要記住,在c++
語言裡,
strings2(s1);
strings3 = s1;
只是語法形式的不同,意義是一樣的,都是定義加初始化,都呼叫拷貝建構函式。 2
)一般來說是在資料成員包含指標物件的時候,應付兩種不同的處理需求的
一種是複製指標物件,一種是引用指標物件
copy
大多數情況下是複製,
=則是引用物件的
例子:classa
顯然 aa,b;
a=b的時候,對於
pdata
資料存在兩種需求
第一種copy
a.pdata=newchar[nlen];
memcpy(a.pdata,b.pdata,nlen);
另外一種
(引用方式):
a.pdata=b.pdata
通過對比就可以看到,他們是不同的
往往把第一種用
copy
使用,第二種用=實現
你只要記住拷貝建構函式是用於類中指標,物件間的copy
3)
拷貝建構函式首先是乙個建構函式,它呼叫的時候產生乙個物件,是通過引數傳進來的那個物件來初始化,產生的物件。
operator=();
是把乙個物件賦值給乙個原有的物件,所以如果原來的物件中有記憶體分配要先把記憶體釋放掉,而且還要檢查一下兩個物件是不是同乙個物件,如果是的話就不做任何操作。
還要注意的是拷貝建構函式是建構函式,不返回值
而賦值函式需要返回乙個物件自身的引用,以便賦值之後的操作
4) 在形式上
類名(形參表列
);//
普通建構函式的宣告,如
box(int h,int w,int len);類名(
類名&
物件名);//
複製建構函式的宣告,如
box(box &b);
5) 在建立物件時,實參型別不同。系統會根據實參的型別決定呼叫普通建構函式或複製建構函式。如
:box box1(12,15,16);//
實參為整數,呼叫普通建構函式
box box2(box1);
//實參是物件名,呼叫複製建構函式
C 拷貝建構函式詳解
一.什麼是拷貝建構函式 首先對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 100 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。include using namespace std class cexam...
C 拷貝建構函式詳解
一.什麼是拷貝建構函式 首先對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 100 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。include using namespace std class cexam...
C 拷貝建構函式詳解
一.什麼是拷貝建構函式 首先對於普通型別的物件來說,它們之間的複製是很簡單的,例如 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。執行程式,螢幕輸出100。從以上 的執行結果可以看出,系統為物件 b 分配了記憶體並完成了與 物件 a 的複製過程...