c 的深拷貝與淺拷貝

2021-05-24 05:49:43 字數 1857 閱讀 2295

所謂淺拷貝,指的是在物件複製時,只是對物件中的資料成員進行簡單的賦值,上面的例子都是屬於淺拷貝的情況,預設拷貝建構函式執行的也是淺拷貝。大多情況下「淺拷貝」已經能很好地工作了,但是一旦物件存在了動態成員,那麼淺拷貝就會出問題了,讓我們考慮如下一段**:

class rect

public:

rect()    //建構函式,p指向對中分配的一空間

p = new int(100);

~rect()  //析構函式,釋放動態分配的空間

if(p != null)

delete p;

private:

int width;

int height;

int *p;    //一指標成員

int main()

rect rect1;

rect rect2(recct1); //複製物件

return 0;

在這段**執行結束之前,會出現乙個執行錯誤。原因就在於在進行物件複製時,對於動態分配的內容沒有進行正確的操作。我們來分析一下:

在執行定義rect1物件後,由於在建構函式中有乙個動態分配的語句,因此執行後的記憶體情況大致如下:

rect1物件                  堆

p      --------->     100

在使用rect1複製rect2時,由於執行的是淺拷貝,只是將成員的值進行賦值,所以此時rect1.p和rect2.p具有相同的值,也即這兩個指標指向了堆裡的同乙個空間,如下圖所示:

rect1物件                  堆                  rect2物件

p      --------->     100         <---------  p

當然,這不是我們所期望的結果,在銷毀物件時,兩個物件的析構函式將對同乙個記憶體空間釋放兩次,這就是錯誤出現的原因。我們需要的不是兩個p有相同的值,而是兩個p指向的空間有相同的值,解決辦法就是使用「深拷貝」。

在「深拷貝」的情況下,對於物件中動態成員,就不能僅僅簡單地賦值了,而應該重新動態分配空間,如上面的例子就應該按照如下的方式進行處理:

class rect

public:

rect()    //建構函式,p指向分配的一空間

p = new int(100);

rect(const rect &r)

width = r.width;

height = r.height;

p = new int;    //為新物件重新動態分配空間;

*p = *(r.p);

~rect()  //析構函式,釋放動態分配的空間

if(p != null)

delete p;

private:

int width;

int height;

int *p; //一指標成員

此時,在完成物件的複製後,記憶體的乙個大致情況如下:

rect1物件                  堆

p      --------->     100

rect2物件

p      --------->     100

此時rect1的p和rect2的p各自指向一段記憶體空間,但它們指向的空間具有相同的內容,這就是所謂的「深拷貝」。

此外,在與「物件的複製」很類似的「物件的賦值」的情況下,也會出現同樣的問題。在「物件的賦值」一文中再來討論此問題。

通過對物件複製的分析,我們發現物件的複製大多在進行「值傳遞」時發生,這裡有乙個小技巧可以防止按值傳遞——宣告乙個私有拷貝建構函式。甚至不必去定義這個拷貝建構函式,這樣因為拷貝建構函式是私有的,如果使用者試圖按值傳遞或函式返回該類物件,將得到乙個編譯錯誤,從而可以避免按值傳遞或返回物件。

C 深拷貝 與 淺拷貝

最近在寫一些c 程式,遇到個問題,記憶體會出錯,查了一些材料,終於發現問題所在了,原來碰到了傳說中的深拷貝和淺拷貝問題了,檢視一些材料,現在對這個問題做個總結 在類定義中,預設是淺拷貝,即 位拷貝 用在基本類中或者一些沒有指標的自定義型別中沒有一點問題,但是當遇到含有指標變數的自定義型別的時候,就會...

C 淺拷貝與深拷貝

淺拷貝 shallow copy 指的是當物件的字段被拷貝的時候,字段應用的物件不會被拷貝。深拷貝是對物件例項當中的字段引用的物件也進行拷貝的一種方式。淺拷貝可以通過將類實現介面icloneable class myclass icloneable 舉個簡單的例項 using system usin...

c 深拷貝與淺拷貝

對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。iostream using namespace std class cexample void show ...