C 解析深淺拷貝

2021-10-06 02:55:05 字數 3598 閱讀 4564

首先我們看看淺拷貝。淺拷貝就是將物件中的所有字段複製到新物件中去,淺拷貝對於值型別和引用型別有不同的影響。值型別的值被複製到副本中後,修改副本中的值不會影響原來物件的值。然而引用型別被複製到副本中的是引用型別的引用。不是引用的物件。這樣再修改副本中的值是會導致原來物件的值也被修改了。但是這裡引用型別情況我們需要排除字串string型別。

那麼為何引用型別修改副本的值會造成原來物件的值的變化,而string字串型別卻排除在外呢?首先我們需要知道這麼乙個概念,string型別是乙個不可變的資料型別,也就是意味著對字串物件進行了初始化,該字串物件就不能改變了。表面上我們修改字串的內容的方法和運算實際上是建立了乙個新字串,然後根據需要可以把舊字串的內容複製到新字串中。怎麼理解你?我們看下面這個案例:

#region  字串比較

//////獲取引用型別的記憶體位址方法

/// ///

///public

static

string getmemory(object

o)

//////

字串比較

這裡我們看a=」123」,b=」123」。我們看他們的引用位址是一樣的。也就是說我們先建立a的時候建立了字串a,有了乙個引用位址。然後我們建立b的時候首先會尋找是否存在相同的值。如果存在相同的值就獲取其引用位址。這也就是為什麼a與b的引用位址是一樣的。這裡涉及到乙個叫做字元駐留池的東西。會對字串進行儲存。那麼後面我們修改b的值然後輸出其引用位址,發現和之前的引用位址不一樣。說明並不是修改原來的值,而是重新建立了乙個字串,重新獲取了它的引用位址。

我們接下來看乙個淺拷貝的案例吧,首先我們準備的是以下的資料型別的值:int,string,enum,struct,class,int,string。

///

///列舉

/// public

enum

enumtest

//////

結構體

/// public

struct

structtest

}//////

/// public

class

classtest

}//////

深拷貝

/// public

class

deepclone : icloneable

;public

string arrstring = new

string ;

public

object

clone()

}class

program

\t\t 備份物件:");

console.writeline($

"string 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"enum 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"struct 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"class 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"int陣列 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"string陣列 型別變化 原物件:\t\t 備份物件:");} }

我們通過繼承icloneable介面對這些型別都進行了淺拷貝然後修改副本物件。輸出原物件和副本物件進行比較。我們發現int,enum,struct、值型別以及string這個特殊的引用型別的原物件值沒有被影響改變。但是class,int,string這些引用型別物件原物件被影響改變了值。也就再次驗證了我們前面說的。淺拷貝是將物件進行賦值到乙個副本物件中去,值型別複製值,引用型別複製其引用物件。修改副本物件值,值型別和string原物件不會被影響改變,引用型別除string其原物件都會被影響改變。

我們上面看了淺拷貝,淺拷貝還是有一定的影響的,處理不好可能就成bug。那麼我們看看對應的深拷貝又是什麼樣的呢?這裡可以先宣告,深拷貝對值型別和引用型別都沒有區別對待。深拷貝也是將物件中的所有字段複製到新物件中去,但是物件無論是值型別還是引用型別都將被重新建立然後複製到副本物件去。對於副本物件的修改將不會影響到原物件,無論任何型別。

我們繼續將上面的例子進行深拷貝看看:

///

///深拷貝

/// public

class

deepclone : icloneable

;public

string arrstring = new

string ;

public

object

clone()

}class

program

\t\t 備份物件:");

console.writeline($

"string 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"enum 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"struct 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"class 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"int陣列 型別變化 原物件:\t\t 備份物件:");

console.writeline($

"string陣列 型別變化 原物件:\t\t 備份物件:");} }

這裡我們看這個執行結果,無論值型別還是引用型別修改副本物件之後都沒有影響原物件的值。這也就是深拷貝的特點了。

我們看完了淺拷貝與深拷貝,我們仔細回顧下。淺拷貝將物件的字段複製到新的物件中去,但是當修改新物件的時候,值型別和string型別的字段將不會影響原物件的字段,而引用型別除string型別外都將影響原物件的值。深拷貝也是將物件的字段複製到新的物件中去,但是無論是值型別還是引用型別的改變都不會影響原物件的值。因為深拷貝是將原物件重新建立然後複製到副本物件中去的。

人生只有走出來的美麗,沒有等出來的輝煌。

《深 淺拷貝解析(C )》

問題 在c 中如果沒有顯式定義拷貝建構函式,編譯系統會生成預設的拷貝建構函式,這種機制方便程式設計師編寫程式的同時也為程式設計師帶來了一些麻煩。當類中含有指標成員變數時,預設的拷貝建構函式會將拷貝函式的指標變數值賦給待拷貝建構函式的指標變數,使兩個指標變數指向同一片空間,物件銷毀時,析構函式就會釋放...

C 深淺拷貝

當結構體中沒有指標時,可進行淺拷貝,資料也會從乙個結構體拷貝到另乙個結構體 兩個結構體都存乙份資料 但當結構體中有指標的時候,假如使用使用淺拷貝,會使兩個結構體使用的指標都指向同乙個記憶體位址,在析構的時候會造成記憶體洩漏。深拷貝 需要對含有指標的結構體,使用 new 申請新的記憶體空間去儲存拷貝的...

c 深淺拷貝

對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。執行程式,螢幕輸出100。從以上 的執行結果可以看出,系統為物件b分配了記憶體並完成了與物件a的複製過程。就...