面試重點 淺拷貝和深拷貝

2021-09-28 23:21:52 字數 2437 閱讀 2225

淺拷貝:簡單的複製拷貝操作

淺拷貝帶來的問題就是:堆區的記憶體重複釋放,

要利用深拷貝解決

深拷貝:在堆區重新申請空間,進行拷貝操作

**總結:**如果屬性有在堆區開闢的,一定要自己提供拷貝建構函式,防止淺拷貝帶來的問題

#include

"pch.h"

#include

using

namespace std;

class

person

person

(int age,

int height)

//自己實現乙個拷貝建構函式,解決淺拷貝帶來的問題

person

(const person &p)

~person()

cout <<

"析構函式呼叫"

<< endl;

}int m_age;

int* m_height;

//指向身高,開闢到堆區};

void

test01()

intmain()

深拷貝和淺拷貝

深拷貝和淺拷貝最根本的區別在於是否真正獲取乙個物件的複製實體,而不是引用。

【區別】:

淺拷貝(shallowcopy)只是增加了乙個指標指向已存在的記憶體位址,

深拷貝(deepcopy)是增加了乙個指標並且申請了乙個新的記憶體,使這個增加的指標指向這個新的記憶體,

使用深拷貝的情況下,釋放記憶體的時候不會因為出現淺拷貝時釋放同乙個記憶體的錯誤。

【理解】:淺拷貝:僅僅是指向被複製的記憶體位址,如果原位址發生改變,那麼淺複製出來的物件也會相應的改變。

深拷貝:在計算機中開闢一塊新的記憶體位址用於存放複製的物件。

例如:假設b複製了a,修改a的時候,看b是否發生變化:

如果b跟著也變了,說明是淺拷貝,拿人手短!(修改堆記憶體中的同乙個值)

如果b沒有改變,說明是深拷貝,自食其力!(修改堆記憶體中的不同的值)

c++中拷貝建構函式的淺拷貝與深拷貝

定義了乙個類,並且例項化了乙個物件,想要複製此物件時(也就是已有的物件),如果沒有自己重寫拷貝建構函式,那麼會預設呼叫系統的拷貝建構函式(淺拷貝)。

【例子1】

#include

using

namespace std;

class

student;

student::

student()

student::

~student()

intmain()

system

("pause");

return0;

}

執行後:

執行結果:呼叫一次建構函式,呼叫兩次析構函式,兩個物件的指標成員所指記憶體相同,這會導致什麼問題呢?name指標被分配一次記憶體,但是程式結束時該記憶體卻被釋放了兩次,會導致崩潰!

【原因】

這是由於編譯系統在我們沒有自己定義拷貝建構函式時,會在拷貝物件時呼叫預設拷貝建構函式,進行的是淺拷貝!即對指標name拷貝後會出現兩個指標指向同乙個記憶體空間。

所以,在對含有指標成員的物件進行拷貝時,必須要自己定義拷貝建構函式,使拷貝後的物件指標成員有自己的記憶體空間,即進行深拷貝,這樣就避免了記憶體洩漏發生。

【例子2】新增了自己定義拷貝建構函式的例子:

#include

using

namespace std;

class

student;

student::

student()

student::

~student()

student::

student

(const student &s)

intmain()

system

("pause");

return0;

}

執行結果:

呼叫一次建構函式,以及一次自定義拷貝建構函式,

兩次析構函式。兩個物件的指標成員所指記憶體不同。

總結:淺拷貝只是對指標的拷貝,拷貝後兩個指標指向同乙個記憶體空間,深拷貝不但對指標進行拷貝,而且對指標指向的內容進行拷貝,經深拷貝後的指標是指向兩個不同位址的指標。

【注意】

當物件中存在指標成員時,除了在複製物件時需要考慮自定義拷貝建構函式,還應該考慮以下兩種情形:

1.當函式的引數為物件時,實參傳遞給形參的實際上是實參的乙個拷貝物件,系統自動通過拷貝建構函式實現;

2.當函式的返回值為乙個物件時,該物件實際上是函式內物件的乙個拷貝,用於返回函式呼叫處。

3.淺拷貝帶來問題的本質在於析構函式釋放多次堆記憶體,使用std::shared_ptr,可以完美解決這個問題。

深拷貝和淺拷貝

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