拷貝(複製)為物件建立副本,即將物件中的所有字段複製到新的物件(副本中)。拷貝有兩種:淺拷貝和深拷貝,微軟建議用型別繼承icloneable介面的方式明確該型別是可以被拷貝的,icloneable介面只提供了乙個clone方法,需要根據需要在clone方法內實現淺拷貝或深拷貝。
1、淺拷貝:把源物件中的值型別欄位的值和引用型別欄位的引用複製到副本中。在源物件(副本)中,修改值型別欄位的值不會影響到副本(源物件),而修改引用型別欄位的值會影響到副本(源物件)。
注意:string型別除外,雖然string型別是引用型別,但是由於該引用型別的特殊性,在淺拷貝過程,副本中會建立新的字串並把對應的值複製過來,字串應被看成值型別。淺拷貝宣告**,使用object.meberwiseclone方法進行淺拷貝:
1class
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 = newemployee()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 ...