C 的淺拷貝和深拷貝(結構體)

2022-05-10 15:12:48 字數 2630 閱讀 2169

關於淺拷貝和深拷貝這個問題遇上的次數不多,這次遇上整理一下,先說這樣乙個問題,關於淺拷貝的問題,先從最簡單的說起。

假設存在乙個結構體:

struct student;  

int main()

; struct student stu2 = ;

stu2 = stu;

cout<

age is : 18

name is :liming

說明此時的拷貝是成功的,此時的結構體可以通過「=」來直接進行賦值操作,但是接下來的問題產生了,假設存在如下的結構體:​

struct stu

; int main()

​產生的結果是這樣的:

s2 345, y, rabbit is cute

s1 ptr: 7934, s2 ptr : 7934

可以看到的是s2 確實得到了s1 傳遞的值,但是第二句的話卻說明這樣的乙個問題,其實s2和s1的指標p都指向乙個記憶體位址,這又說明了什麼?

這說明指標的並沒有將內容複製一塊給新指標來指向,只是讓新指標指向原來的那個記憶體,這樣就相當於,指標在這個複製的過程中只是複製了位址,而不是內容。

原理:

在拷貝過程中,如果沒有自定義拷貝建構函式,系統會提供乙個預設的拷貝建構函式,預設的拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別成員變數,呼叫其相應型別的拷貝建構函式。但是注意預設的建構函式卻是這樣的:預設拷貝建構函式在拷貝過程中是按位元組複製的,對於指標型成員變數只複製指標本身,而不複製指標所指向的目標--淺拷貝。

這就是產生問題的原因了,淺拷貝出現了。。。

用下圖來解釋這個問題:

在進行物件複製後,事實上s1、s2裡的成員指標p都指向了一塊記憶體空間(即記憶體空間共享了),在s1析構時,delete了成員指標p所指向的記憶體空間,而s2析構時同樣指向(此時已變成野指標)並且要釋放這片已經被s1析構函式釋放的記憶體空間,這就讓同樣一片記憶體空間出現了「double free」 ,從而出錯。而淺拷貝還存在著乙個問題,因為一片空間被兩個不同的子物件共享了,只要其中的乙個子物件改變了其中的值,那另乙個物件的值也跟著改變了。

為了實現深拷貝,往往需要自己定義拷貝建構函式,在源**裡,我們加入自定義的拷貝建構函式如下:

在結構體中加入自己的拷貝建構函式:

struct stu;};

int main()

測試demo

#define _crt_secure_no_warnings

#include #include using namespace std;

class stu

//strcpy(pp, stutmp.p);

return *this;

};};

int main()

相當於過載operator=方法,這樣還是執行,產生的結果就是這樣的:

s2 345, y, rabbit is cute

s1 ptr: 7910, s2 ptr : 1050000

printf("s1 ptr: %s, s2 ptr : %s\n ", s1.p, s2.p);

產生的結果是:s1 ptr: rabbit is cute, s2 ptr : rabbit is cute

此時s1和s2中的p指標位址不同,但是指向的內容一致,所以這拷貝成功。​

其實類的結構和上面的結構體是類似的,其實可以將結構體看成乙個類來處理,結構體也可有自己的構造、析構、過載運算子河函式,可以簡單的認為結構體是類的一種形式。

拷貝有兩種:深拷貝,淺拷貝

當出現類的等號賦值時,會呼叫拷貝函式 在未定義顯示拷貝建構函式的情況下,系統會呼叫預設的拷貝函式——即淺拷貝,它能夠完成成員的一一複製。當資料成員中沒有指標時,淺拷貝是可行的。 但當資料成員中有指標時,如果採用簡單的淺拷貝,則兩類中的兩個指標將指向同乙個位址,當物件快結束時,會呼叫兩次析構函式,而導致指標懸掛現象。 所以,這時,必須採用深拷貝。 深拷貝與淺拷貝的區別就在於深拷貝會在堆記憶體中另外申請空間來儲存資料,從而也就解決了指標懸掛的問題。 簡而言之,當資料成員中有指標時,必須要用深拷貝。​

​建議:

我們在定義類或者結構體,這些結構的時候,最後都重寫拷貝建構函式,避免淺拷貝這類不易發現但後果嚴重的錯誤產生。​

結構體的深拷貝和淺拷貝

示例 define crt secure no warnings include include include typedef struct teacher teacher 淺拷貝 編譯器的操作只會把指標變數的值,從from copy到 to,但不會把指標變數所指的記憶體空間給拷貝過去 void ...

結構體的深拷貝和淺拷貝問題

如果結構體中有指標 在堆上開闢的空間 以下這個拷貝函式,就是淺拷貝 結構體可以通過變數直接賦值,但不要使用這種方法,要給結構體中的成員 乙個乙個拷貝 void copy teacher struct teacher to,struct teacher from void copy teacher d...

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指向同乙個物件,當析構的時候,同...