結構體的淺複製和深複製

2021-08-25 19:07:23 字數 2604 閱讀 6933

淺複製,指在建立乙個物件或結構的副本時,對其值型別字段直接複製值,引用型別欄位只複製引用(位址)。

深複製,與淺複製不同的是,對引用型別字段,會建立新的引用,使用新的引用(位址)。

通常直接賦值操作是淺複製操作,若使用深複製,應該實現icloneable操作,寫clone方法,利用object.memberwiseclone方法淺複製後,需要手動編寫對其引用物件進行建立新的物件深複製副本。

結構體也是如此,雖然是值型別,若其中包含引用型別字段,想產生乙個深複製版本,必須手動實現。

下面是乙個測試結構體淺複製的**:

using system; using system.linq; class program ; //~ 直接賦值,使s2=s1 //~ 顯示資料完成相同 console.writeline("test 1:"); var s2=s1; console.writeline("s1: "+s1); console.writeline("s2: "+s2); console.writeline(); //~ 直接修改s2的值型別資料(firstpoint)和引用型別資料(otherpoint) //~ 值型別資料的改變不影響s1,引用型別資料的改變影響s1 console.writeline("test 2:"); s2=s1; console.writeline("s1: "+s1); s2.title="i'm s2"; s2.firstpoint.x=50; s2.firstpoint.y=50; s2.otherpoint[0].x=150; s2.otherpoint[0].y=150; s2.otherpoint[1].x=250; s2.otherpoint[1].y=250; console.writeline("s2: "+s2); console.writeline("s1: "+s1); console.writeline(); //~ 使用new更改變值型別(firstpoint)和引用型別(otherpoint) //~ 值型別改變不影響s1,引用型別改變沒影響s1 console.writeline("test 3:"); s2=s1; s2.title="i'm s2"; console.writeline("s1: "+s1); s2.firstpoint=new point(-99,-98); s2.otherpoint=new point; console.writeline("s2: "+s2); console.writeline("s1: "+s1); console.writeline(); //~ otherpoint是個陣列,s2=s1後,建立這個陣列的副本 //~ s2.otherpoint的改變不再影響s1.otherpoint的改變 console.writeline("test 4:"); s2=s1; s2.otherpoint=s1.otherpoint.toarray(); //建立乙個副本 s2.title="i'm s2"; console.writeline("s1: "+s1); s2.firstpoint.x=1; s2.firstpoint.y=2; s2.otherpoint[0].x=3; s2.otherpoint[0].y=4; s2.otherpoint[1].x=5; s2.otherpoint[1].y=6; console.writeline("s2: "+s2); console.writeline("s1: "+s1); //~ 結論:結構體物件中的引用型別,在結構體所在的棧中只儲存了引用物件的引用(指標), //~ 使用簡單賦值操作(s2=s1),不會在託管堆中建立引用物件的副本,它們將共同使用同一 //~ 引用物件。即,結構體的簡單賦值操作(s2=s1)是對棧中結構體資料進行淺複製。 //~ 注:字串物件system.string為特別的引用型別,具有值型別行為,因此,結論中的 //~ 引用物件不包含字串型別物件。 } } //具有引用型別的結構體 struct s1 } return string.format(" -",title,firstpoint,otherpointstr); } } //最簡單的結構體 struct point public override string tostring() ,)",x,y); } }

顯示結果:

>test test 1: s1: i'm s1 (0,0)-(1,1)(2,2) s2: i'm s1 (0,0)-(1,1)(2,2) test 2: s1: i'm s1 (0,0)-(1,1)(2,2) s2: i'm s2 (50,50)-(150,150)(250,250) s1: i'm s1 (0,0)-(150,150)(250,250) test 3: s1: i'm s1 (0,0)-(150,150)(250,250) s2: i'm s2 (-99,-98)-(-1,-1)(-2,-2) s1: i'm s1 (0,0)-(150,150)(250,250) test 4: s1: i'm s1 (0,0)-(150,150)(250,250) s2: i'm s2 (1,2)-(3,4)(5,6) s1: i'm s1 (0,0)-(150,150)(250,250) >exit code: 0 time: 0.225

測試**中前三個test,使s2=s1操作後,s2得到了s1的乙個淺複製版本。

test 4利用system.linq提供的擴充套件方法toarray建立了陣列的乙個副本,

使s2是s1的深複製版本,所以演示中對s2的任何修改不會影響s1。

注意:使用toarray方法,根據情況,增加源資料物件是否為null的判斷。

淺複製和深複製

在c 中,下面三種物件需要呼叫拷貝建構函式 有時也稱 複製建構函式 1 乙個物件作為函式引數,以值傳遞的方式傳入函式體 全域性函式,傳入的是物件 void g fun resume c 2 乙個物件作為函式返回值,以值傳遞的方式從函式返回 全域性函式 返回的是物件 resume g fun 3 乙個...

深複製和淺複製

以下 是否完全正確,執行可能得到的結果是 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class a class b b void sayhello b b int main 程式正常執行 程式編譯錯誤 程式崩潰 程式死迴圈 這個程式會直接崩潰 voidsayhello ...

深複製和淺複製

main.m 深複製和淺複製。created by yaomars on 16 4 27.import 建立乙個nsdictionary,並建立可變副本和不可變副本,說下是深複製還是淺複製。int main int argc,const char argv 第三種方式 建立乙個nsdictionar...