c 中的 深拷貝 與 淺拷貝 詳解

2021-10-12 16:04:16 字數 1783 閱讀 9510

在c++中,深拷貝和淺拷貝也算是乙個難點,特別是對於初學者來說,往往在不知道兩者區別的情況下而錯誤的使用了淺拷貝,從而導致了野指標之類的問題,但是又因為缺少理解所以很難定位到問題所在。

深拷貝和淺拷貝最根本的區別在於是否真正獲取乙個物件的完全複製實體,而不是引用。所謂完全複製實體即是在包含指標變數的時候,不是僅僅的把指標複製一下,而是要更深一步,把指標所指的內容同樣複製過來。

我還是舉個例子吧

第一種情況:此類的類成員變數有指標變數的時候

class

a

第二種情況:此類的類成員變數的類成員變數中有指標變數並且包含該指標變數的類的拷貝建構函式同樣是淺拷貝的情況下
class

aclass

b

上述第一種情況,類a中包含了乙個指標變數b;第二種情況的例子中,類b雖然沒有包含指標變數,但是它包含了變數a,a中包含了乙個指標型別的成員變數b,同時類a的賦值建構函式並沒有定義,因此會是預設的淺拷貝(這裡要講一下,第二種情況的例子中:在b的物件呼叫拷貝建構函式時,物件內部包含的變數b和a在被拷貝時同樣會呼叫自身的拷貝建構函式來進行拷貝)。這兩種情況下都非常有可能出現野指標的問題。

下面會繼續介紹為什麼會出現問題,以及怎樣才算是深拷貝。

怎樣才算是深拷貝 以及 為什麼會出現問題

下面依舊通過例子給你們介紹深拷貝和淺拷貝。

先來看淺拷貝

class

a

上方類a中沒有自己定義拷貝建構函式,因此當我們呼叫拷貝建構函式時,會呼叫編譯器自動生成的拷貝建構函式。

你可能就要問了,預設生成的拷貝建構函式會進行哪些操作呢?

比如:

classa;

int main()

上述**第11行中即進行了一次拷貝建構函式的呼叫,同時因為沒有自己定義拷貝建構函式,所以會使用系統預設的淺拷貝。

具體的操作有:

首先,將a1的a變數拷貝到a2的a變數中,這一步沒有什麼問題。

其次,會將a1的b變數的值拷貝到a2的b變數中,注意:這裡只是將值拷貝到a2,指標變數的值代表的是此指標所指向的變數的記憶體位址,因此,拷貝完之後的a1和a2中的指標變數b同時指向同乙個記憶體位址。

上述就是淺拷貝。

為什麼會出現問題

看到這裡你可能就要意識的問題了吧。

當兩個指標同時指向同一塊記憶體位址時,輕則:a1中的b指針對變數進行改變後,當使用a2中的b指標訪問時,變數已經被a1改變,會引發一些意想不到的問題;重則:當a1將指標變數b釋放後,a2若再使用指標變數b則會引發野指標問題,即訪問非法記憶體位址。

再看深拷貝

如何實現深拷貝呢?

首先要知道,要實現深拷貝,需要自己定義拷貝建構函式,同時在實現函式時要對指標變數進行深層次的拷貝,即去拷貝指標所指向的位置的變數。

classa}

;

如上述**,再進行拷貝構造時,會複製乙個指標b所指向變數的複製體d,然後再將本身的指標變數b指向此複製體d,如此即為深拷貝。

進一步思考,上述所講的第二種情況:

classa}

;class

b

上述**中類a定義了拷貝建構函式,同時是深拷貝因此不會出現野指標的問題,而如果類a沒有實現深拷貝,同樣會出現問題。

思考一下吧。

C 深拷貝與淺拷貝 詳解

include using namespace std class test test test int p,int n test test void test show int main void test a b,88 a.show 上面的拷貝建構函式不夠正規,現在寫乙個常用的拷貝建構函式 in...

c 中深拷貝與淺拷貝

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

C 中的淺拷貝與深拷貝

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