淺拷貝和深拷貝

2021-08-07 13:00:00 字數 2418 閱讀 9487

預設拷貝建構函式

很多時候在我們都不知道拷貝建構函式的情況下,傳遞物件給函式引數或者函式返回物件都能很好的進行,這是因為編譯器會給我們自動產生乙個拷貝建構函式(預設拷貝建構函式),這個建構函式很簡單,僅僅使用「老物件」的資料成員的值對「新物件」的資料成員一一進行賦值,它一般具有以下形式:

rect::rect(const rect& r)  

class

rect

~rect() // 析構函式,計數器減1

static

int getcount() // 返回計數器的值

private:

int width;

int height;

static

intcount; // 一靜態成員做為計數器

};

int rect::count = 0; // 將類rect中的成員count初始化

int main()

這段**對前面的類,加入了乙個靜態成員,目的是進行計數。在主函式中,首先建立物件rect1,輸出此時的物件個數,然後使用rect1複製出物件rect2,再輸出此時的物件個數,按照理解,此時應該有兩個物件存在,但實際程式執行時,輸出的都是1,反應出只有1個物件。此外,在銷毀物件時,由於會呼叫銷毀兩個物件,類的析構函式會呼叫兩次,此時的計數器將變為負數。

說白了,就是拷貝建構函式沒有處理靜態資料成員。

出現這些問題最根本就在於在複製物件時,計數器沒有遞增,我們重新編寫拷貝建構函式,如下:

class

rect

rect(const rect& r) // 拷貝建構函式

~rect() // 析構函式,計數器減1

static

int getcount() // 返回計數器的值

private:

int width;

int height;

static

intcount; // 一靜態成員做為計數器

};

淺拷貝

指在物件複製時,只對物件中的資料成員進行簡單的賦值,預設拷貝建構函式執行的也是淺拷貝。大多情況下「淺拷貝」已經能很好地工作了,但是一旦物件存在了動態成員,那麼淺拷貝就會出問題了。

深拷貝

在「深拷貝」的情況下,對於物件中動態成員,就不能僅僅簡單地賦值了,而應該重新動態分配空間。

防止預設拷貝發生

通過對物件複製的分析,我們發現物件的複製大多在進行「值傳遞」時發生,這裡有乙個小技巧可以防止按值傳遞——宣告乙個私有拷貝建構函式。甚至不必去定義這個拷貝建構函式,這樣因為拷貝建構函式是私有的,如果使用者試圖按值傳遞或函式返回該類物件,將得到乙個編譯錯誤,從而可以避免按值傳遞或返回物件。

四. 拷貝建構函式的幾個細節

1. 拷貝建構函式裡能呼叫private成員變數嗎?

解答:我們知道拷貝建構函式其實就是乙個特殊的建構函式,操作的還是自己類的成員變數,所以不受private的限制。

以下函式哪個是拷貝建構函式,為什麼?

x::x(const x&);      

x::x(x);

x::x(x&, int a=1);

x::x(x&, int a=1, int b=2);

解答:對於乙個類x, 如果乙個建構函式的第乙個引數是下列之一:

a) x&

b) const x&

c) volatile x&

d) const volatile x&

且沒有其他引數或其他引數都有預設值,那麼這個函式是拷貝建構函式.

x::x(const x&);  //是拷貝建構函式      

x::x(x&, int=1); //是拷貝建構函式

x::x(x&, int a=1, int b=2); //當然也是拷貝建構函式

乙個類中可以存在多於乙個的拷貝建構函式嗎?

解答:類中可以存在超過乙個拷貝建構函式。

class x ;
注意,如果乙個類中只存在乙個引數為 x& 的拷貝建構函式,那麼就不能使用const x或volatile x的物件實行拷貝初始化.

class x ;      

const x cx;

x x = cx; // error

如果乙個類中沒有定義拷貝建構函式,那麼編譯器會自動產生乙個預設的拷貝建構函式。

這個預設的引數可能為 x::x(const x&)或 x::x(x&),由編譯器根據上下文決定選擇哪乙個。

深拷貝和淺拷貝

淺拷貝就是物件的資料成員之間的簡單賦值,如你設計了乙個沒有類而沒有提供它的複製建構函式,當用該類的乙個物件去給令乙個物件賦值時所執行的過程就是淺拷貝,如 class a a private int data int main 這一句b a 就是淺拷貝,執行完這句後b.data 5 如果物件中沒有其他...

淺拷貝和深拷貝

以下情況都會呼叫拷貝建構函式 乙個物件以值傳遞的方式傳入函式體 例如 已知class a,class b void func a a void func a a func b b 此時函式對b的操作是呼叫拷貝建構函式後的臨時拷貝物件。多數傳指標 乙個物件以值傳遞的方式從函式返回 如 return b...

深拷貝和淺拷貝

ios提供了copy和mutablecopy方法,顧名思義,copy就是複製了乙個imutable的物件,而mutablecopy就是複製了乙個mutable的物件。以下將舉幾個例子來說明。1 系統的非容器類物件 這裡指的是nsstring nsnumber等等一類的物件。nsstring stri...