c 從淺拷貝和深拷貝到預設拷貝函式

2022-07-07 11:36:08 字數 2026 閱讀 5071

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

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

//深度拷貝

int a = 5;

int b = a;

所謂深度拷貝,即為在堆疊記憶體中新開闢了一塊區域,儲存著拷貝過來的資料。以上述**為例,a和b分別指向記憶體中不同的位址,而兩部分位址中儲存著相同的5。

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

//淺拷貝

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);

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

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

類的預設拷貝建構函式採用的是淺拷貝,也就是說拷貝者和被拷貝者的指向的記憶體空間是一致的。

在以下情況中:

1、通過使用另乙個同型別的物件來初始化新建立的物件,即用已有物件給新建立物件賦值。

2、物件作為函式引數並且發生值傳遞時。

3、物件作為函式返回值並且發生值傳遞時。

拷貝建構函式會被呼叫,現在我們分別看一下如果類中含有動態分配空間的話以上三種情況下會發生什麼。

1、通過使用另乙個同型別的物件來初始化新建立的物件。

line line2 = line1;//呼叫預設拷貝建構函式
由於發生了淺拷貝,現在line2和line1指向的是同一塊記憶體空間,由於類中含有動態分配的空間,當main函式結束時,這些空間被釋放,就出現了line1與line2釋放同一處空間的情況,編譯器會報錯:

即發生了對同一塊記憶體空間的重複釋放,而這一般是不被允許的。

2、物件作為函式引數並且發生值傳遞時。

由引數傳遞的知識,我們可以知道,發生值傳遞時,是用實參通過拷貝建構函式來對形參賦值,形參與實參在預設拷貝下會指向同一段記憶體空間。

void display(line obj)

{ cout << "line 大小 : " << obj.getlength() 上例中,形參obj與實參line中動態分配部分指向同一段記憶體,當函式呼叫結束時,形參obj被消滅,與此同時,本來由line指向的記憶體空間被釋放,line變成了指向一段自由空間,這也是不被允許的。

3、物件作為函式返回值並且發生值傳遞時。

這裡也是發生了值傳遞,道理和2、是一樣的,不再贅述。

為避免上述問題,當類中含有動態分配空間時,自定義乙個深度拷貝的拷貝建構函式和賦值運算子是必要的。具體構造方法請看本人部落格裡另兩篇文章《c++拷貝(複製)建構函式》和《c++類賦值運算子過載》

前端的深拷貝和淺拷貝 深拷貝與淺拷貝到底是什麼

複製建構函式也叫拷貝建構函式 淺複製也叫淺拷貝或位拷貝 深複製也叫深拷貝 淺拷貝和深拷貝拷貝就是複製,建立副本。假設有物件a,a有屬性t1,t2。那麼,我通過拷貝a,得到b,b應該也有屬性t1,t2,且a b兩個物件的每個屬性,都應該是相同的。對於基本型別的屬性t1,拷貝是沒有疑義的。簡單將值複製乙...

C 淺拷貝和深拷貝

class test test const test t val new int t.val test private int val 現在定義兩個物件,test t1 9 test t2 t1 如果你不提供copy建構函式 注釋掉的那個 那麼t1和t2的成員 val指向同乙個物件,當析構的時候,同...

c 深拷貝和淺拷貝

深拷貝和淺拷貝 ca const ca c 就是我們自定義的拷貝建構函式。可見,拷貝建構函式是一種特別的建構函式,函式的名稱必須和類名稱一致,他的唯一的乙個引數是本型別的乙個引用變數,該引數是const型別,不可變的。例如 類x的拷貝建構函式的形式為x x x 當用乙個已初始化過了的自定義類型別物件...