淺拷貝和深拷貝

2021-09-02 01:40:38 字數 2829 閱讀 8880

1. c++類的預設拷貝建構函式的弊端

c++類的中有兩個特殊的建構函式,(1)無參建構函式,(2)拷貝建構函式。它們的特殊之處在於:

(1)當類中沒有定義任何建構函式時,編譯器會預設提供乙個無參建構函式且其函式體為空;

(2)當類中沒有定義拷貝建構函式時,編譯器會預設提供乙個拷貝建構函式,進行成員變數之間的拷貝。(這個拷貝操作是淺拷貝)

這裡只講拷貝建構函式。在c語言中,

int a = 5;  //初始化

int b;

b = 6; //賦值

上面的初始化及賦值操作是最正常不過的語法,c++語言肩挑相容c語言語法的責任,所以在類的設計上,也相容這種操作:

class cls

int main(void)

如上的初始化類需要呼叫到cls類的預設實現的拷貝建構函式,為類賦值需要呼叫的是cls類的預設實現的賦值操作符過載函式,它們都是淺度拷貝的。前者其原型為:

cls(const cls& c)
預設的拷貝建構函式存在弊端,看如下類定義:

class testcls

~testcls() //析構函式

};

類中的指標p在建構函式中分配的空間,在析構函式中釋放。

int main(void)

編譯執行確實不會出錯:

類在我們沒有定義拷貝建構函式的時候,會預設定義預設拷貝建構函式,也就是說可以直接用同型別的類間可以相互賦值、初始化:

int main(void)

編譯通過,執行卻出錯了:

原因就在於,預設的拷貝建構函式實現的是淺拷貝。

2. 深度拷貝和淺拷貝

深度拷貝和淺拷貝在c語言中就經常遇到的了,在這裡我簡單描述。

一般的賦值操作是深度拷貝:

//深度拷貝

int a = 5;

int b = a;

簡單的指標指向,則是淺拷貝:

//淺拷貝

int a = 8;

int *p;

p = &a;

char* str1 = "helloworld";

char* str2 = str1;

將上面的淺拷貝改為深度拷貝後:

//深度拷貝

int a = 8;

int *p = new

int;

*p = a;

char* str1 = "helloworld";

int len = strlen(str1);

char *str2 = new

char[len];

memcpy(str2, str1, len);

稍微有點c語言基礎的人都能看得出深度拷貝和淺拷貝的差異。總而言之,拷貝者和被拷貝者若是同乙個位址,則為淺拷貝,反之為深拷貝。

以字串拷貝為例,淺拷貝後,str1和str2同指向0x123456,不管哪乙個指標,對該空間內容的修改都會影響另乙個指標。

深拷貝後,str1和str2指向不同的記憶體空間,各自的空間的內容一樣。因為空間不同,所以不管哪乙個指標,對該空間內容的修改都不會影響另乙個指標。

3. 解決預設拷貝建構函式的弊端

類的預設拷貝建構函式只會用被拷貝類的成員的值為拷貝類簡單初始化,也就是說二者的p指標指向的記憶體空間是一致的。以前面testcls可以知道,編譯器為我們預設定義的拷貝建構函式為:

testcls(const testcls& testcls)

main函式將要退出時,拷貝類t2的析構函式先得到執行,它把自身p指向的堆空間釋放了;接下來,t1的析構函式得到呼叫,被拷貝類t1的析構函式得到呼叫,它同樣要去析構自身的p指向指向的堆空間,但是該空間和t2類中p指向的空間一樣,造成重複釋放,程式執行崩潰。

解決辦法十分簡單,自定義拷貝建構函式,裡面用深度拷貝的方式為拷貝類初始化:

class testcls

testcls(const testcls& testcls)

~testcls()

};int main(void)

編譯執行正常:

關於c++拷貝建構函式的深度拷貝和淺拷貝的介紹到這裡,其實還可以將它們的位址列印出來看看,不過這一步就不再贅述了。

c++的拷貝建構函式還有一處妙用,就是自定義拷貝建構函式,並設定為private屬性,其實現體可以什麼都不寫,那麼這個類將變成乙個不可被複製的類了。

1. c++類的預設拷貝建構函式的弊端

深拷貝和淺拷貝

淺拷貝就是物件的資料成員之間的簡單賦值,如你設計了乙個沒有類而沒有提供它的複製建構函式,當用該類的乙個物件去給令乙個物件賦值時所執行的過程就是淺拷貝,如 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...