C 淺拷貝和深拷貝的實現

2022-07-16 08:51:09 字數 4495 閱讀 5653

拷貝(複製)為物件建立副本,即將物件中的所有字段複製到新的物件(副本中)。拷貝有兩種:淺拷貝和深拷貝,微軟建議用型別繼承icloneable介面的方式明確該型別是可以被拷貝的,icloneable介面只提供了乙個clone方法,需要根據需要在clone方法內實現淺拷貝或深拷貝。

1、淺拷貝:把源物件中的值型別欄位的和引用型別欄位的引用複製到副本中。在源物件(副本)中,修改值型別欄位的值不會影響到副本(源物件),而修改引用型別欄位的值會影響到副本(源物件)。

注意:string型別除外,雖然string型別是引用型別,但是由於該引用型別的特殊性,在淺拷貝過程,副本中會建立新的字串並把對應的值複製過來,字串應被看成值型別。

淺拷貝宣告**,使用object.meberwiseclone方法進行淺拷貝:

1

class

employee : icloneable24

public

int age

5public department departmentname 67

//實現icloneable介面的clone方法

8public

object

clone()912

}13class

department

1416

public department(string

value)

1720

public

override

string

tostring()

2124 }

呼叫淺拷貝**:

1      employee emp1 = new

employee()2;

7 employee emp2 = emp1.clone() as employee;//

淺拷貝8

9 console.writeline("

-------初始化賦值------");

10 console.writeline(string.format("

[emp1] id:\tage:\tdepartment:

", emp1.id, emp1.age, emp1.departmentname));

11 console.writeline(string.format("

[emp2] id:\tage:\tdepartment:

", emp2.id, emp2.age, emp2.departmentname));

1213 console.writeline("

\n-------改變emp1的值-------");

14 emp1.id = "

no2"

;15 emp1.age = 22

;16 emp1.departmentname.departmentname = "

sales";

17 console.writeline(string.format("

[emp1] id:\tage:\tdepartment:

", emp1.id, emp1.age, emp1.departmentname));

18 console.writeline(string.format("

[emp2] id:\tage:\tdepartment:

", emp2.id, emp2.age, emp2.departmentname));

1920 console.writeline("

\n-------改變emp2的值-------");

21 emp2.id = "

no3"

;22 emp2.age = 24

;23 emp2.departmentname.departmentname = "

personnel";

24 console.writeline(string.format("

[emp1] id:\tage:\tdepartment:

", emp1.id, emp1.age, emp1.departmentname));

25 console.writeline(string.format("

[emp2] id:\tage:\tdepartment:

", emp2.id, emp2.age, emp2.departmentname));

執行結果:

-------初始化賦值------[emp1] id:no1   age:

20department:technology

[emp2] id:no1 age:

20department:technology

-------改變emp1的值-------[emp1] id:no2 age:

22department:sales

[emp2] id:no1 age:

20department:sales

-------改變emp2的值-------[emp1] id:no2 age:

22department:personnel

[emp2] id:no3 age:

24 department:personnel

從結果可以看出,age是值型別,id是string型別這裡被當做值型別處理,所以id和age修改了對另乙個物件沒有影響;department屬性是引用型別,淺拷貝emp1和emp2引用的是同乙個department物件,其中乙個修改了departmentname的值會影響另乙個。

2、深拷貝:把源物件的值型別欄位和引用型別字段,重新建立並賦值。在源物件(副本)中,修改值型別欄位的值或者引用型別欄位的值都不會影響到副本(源物件)。

建議使用序列化的形式來進行深拷貝

深拷貝**:

[serializable]//

標記可序列化

class

employee : icloneable

public

int age

public department departmentname

//實現icloneable介面的clone方法

public

object

clone()}}

[serializable]

//標記可序列化

class

department

public department(string

value)

public

override

string

tostring()

}

跟上面呼叫淺拷貝**一樣呼叫深拷貝,執行結果:

-------初始化賦值------[emp1] id:no1   age:

20department:technology

[emp2] id:no1 age:

20department:technology

-------改變emp1的值-------[emp1] id:no2 age:

22department:sales

[emp2] id:no1 age:

20department:technology

-------改變emp2的值-------[emp1] id:no2 age:

22department:sales

[emp2] id:no3 age:

24 department:personnel

拷貝以後,無論是修改值型別還是引用型別,都對另乙個物件沒有影響。

3、要同時實現深拷貝和淺拷貝,可以在clone方法外,額外實現兩個方法,宣告為deepclone和shallow:

1     [serializable]//

標記可序列化

2class

employee : icloneable35

public

int age

6public department departmentname 78

//實現icloneable介面的clone方法

9public

object

clone()

1013

14//

深拷貝15

public

employee deepclone()

1624}25

26//

淺拷貝27

public

employee shallow()

2831 }

參考:《編寫高質量**改善c#程式的157個建議》陸敏技

C 淺拷貝和深拷貝

class test test const test t val new int t.val test private int val 現在定義兩個物件,test t1 9 test t2 t1 如果你不提供copy建構函式 注釋掉的那個 那麼t1和t2的成員 val指向同乙個物件,當析構的時候,同...

c 深拷貝和淺拷貝

深拷貝和淺拷貝 ca const ca c 就是我們自定義的拷貝建構函式。可見,拷貝建構函式是一種特別的建構函式,函式的名稱必須和類名稱一致,他的唯一的乙個引數是本型別的乙個引用變數,該引數是const型別,不可變的。例如 類x的拷貝建構函式的形式為x x x 當用乙個已初始化過了的自定義類型別物件...

c 深拷貝和淺拷貝

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