C 中的深拷貝與淺拷貝

2022-03-28 02:17:34 字數 2990 閱讀 9658

淺拷貝:又稱值拷貝,將源物件的值拷貝到目標物件中去,本質上來說源物件和目標物件共用乙份實體,只是所引用的變數名不同,位址其實還是相同的。舉個簡單的例子,你的小名叫西西,大名叫冬冬,當別人叫你西西或者冬冬的時候你都會答應,這兩個名字雖然不相同,但是都指的是你。

假設有乙個string類,string s1;string s2(s1);在進行拷貝構造的時候將物件s1裡的值全部拷貝到物件s2裡。

我們現在來簡單的實現一下這個類

1 #include 2 #include3

4using

namespace

std;56

class

string

714 string( const string&s )

1518 string& operator=(const string&s)

1924

return *this;25

}2627 ~string()

2835}36

37void

show()

3841

private:42

char*_str;

43};

4445

intmain()

46

其實這個程式是存在問題的,什麼問題呢?我們想一下,建立s2的時候程式必然會去呼叫拷貝建構函式,這時候拷貝構造僅僅只是完成了值拷貝,導致兩個指標指向了同一塊記憶體區域。隨著程式的執行結束,又去呼叫析構函式,先是s2去呼叫析構函式,釋放了它指向的記憶體區域,接著s1又去呼叫析構函式,這時候析構函式企圖釋放一塊已經被釋放的記憶體區域,程式將會崩潰。s1和s2的關係就是這樣的:

進行除錯程式發現s1和s2確實指向了同一塊區域:

所以程式會崩潰是應該的,那麼這個問題應該怎麼去解決呢?這就引出了深拷貝。

深拷貝,拷貝的時候先開闢出和源物件大小一樣的空間,然後將源物件裡的內容拷貝到目標物件中去,這樣兩個指標就指向了不同的記憶體位置。並且裡面的內容是一樣的,這樣不但達到了我們想要的目的,還不會出現問題,兩個指標先後去呼叫析構函式,分別釋放自己所指向的位置。即為每次增加乙個指標,便申請一塊新的記憶體,並讓這個指標指向新的記憶體,深拷貝情況下,不會出現重複釋放同一塊記憶體的錯誤。

深拷貝實際上是這樣的:

深拷貝的拷貝建構函式和賦值運算子的過載傳統實現:

1 string( const string&s )

27 string& operator=(const string&s)816

return *this

;17 }

這裡的拷貝建構函式我們很容易理解,先開闢出和源物件一樣大的記憶體區域,然後將需要拷貝的資料複製到目標拷貝物件,

那麼這裡的賦值運算子的過載是怎麼樣做的呢?

這種方法解決了我們的指標懸掛問題,通過不斷的開空間讓不同的指標指向不同的記憶體,以防止同一塊記憶體被釋放兩次的問題,還有一種深拷貝的現**法:

1 string( const string&s ):_str(null)26

7 string& operator=(const string&s)814

return *this

;15 }

先來分析一下拷貝構造是怎麼實現的:

拷貝構造呼叫完成之後,會接著去呼叫析構函式來銷毀區域性物件tmp,按照這種思路,不難可以想到s2的值一定和拷貝構造裡的tmp的值一樣,指向同一塊記憶體區域,通過除錯可以看出來:

在拷貝建構函式裡的tmp:

呼叫完拷貝構造後的s2:(此時tmp被析構)

可以看到s2的位址值和拷貝構造裡的tmp的位址值是一樣

關於賦值運算子的過載還可以這樣來寫:

string& operator=(string s)

1 #include 2 #include3

4using

namespace

std;56

class

string 714

//string( const string& s )

15//

21//

string& operator=(const string& s)

22//

31//

return *this;

32//}33

34 string( const string&s ):_str(null)

3539

40 string& operator=(const string&s)

4147

return *this;48

}4950 ~string()

5158}59

60void

show()

6164

private:65

char*_str;

66};

6768

intmain()

69

參考與**c++中的深淺拷貝 - qq_39344902的部落格 - csdn部落格

c 中深拷貝與淺拷貝

如果沒有自定義複製建構函式,則系統會建立預設的複製建構函式,但系統建立的預設複製建構函式只會執行 淺拷貝 即將被拷貝物件的資料成員的值一一賦值給新建立的物件,若該類的資料成員中有指標成員,則會使得新的物件的指標所指向的位址與被拷貝物件的指標所指向的位址相同,delete該指標時則會導致兩次重複del...

C 中的淺拷貝與深拷貝

用自定義的string類解釋什麼是淺拷貝什麼是深拷貝。class string 淺拷貝是在呼叫拷貝函式時進行了值拷貝,這樣的拷貝看似沒有問題,在呼叫析構函式時會導致記憶體洩漏,系統奔潰。define crt secure no warnings 1 includeusing namespace st...

C 中的深拷貝與淺拷貝

1 拷貝建構函式 定義 如果乙個類的建構函式的第乙個引數是類自身類型別的引用,且任何額外引數都有預設值,則此建構函式為拷貝建構函式。由此可見,拷貝建構函式是一種特殊的建構函式,乙個類可以有多個拷貝建構函式,既可以是public的,也可以是private的 特殊用法,如設計模式中的單例模式需要將拷貝建...