程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> 深拷貝與淺拷貝探析

深拷貝與淺拷貝探析

編輯:關於C

深拷貝與淺拷貝探析
1.         深拷貝是指源對象與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。舉個例子,一個人名叫張三,後來用他克隆(假設法律允許)了另外一個人,叫李四,不管是張三缺胳膊少腿還是李四缺胳膊少腿都不會影響另外一個人。比較典型的就是Value(值)對象,如預定義類型Int32,Double,以及結構(struct),枚舉(Enum)等。

考慮以下寫法

       int source = int.MaxValue;//(1)初始化源對象為整數的最大值2,147,483,647

            int dest = source;//(2)賦值,內部執行深拷貝

            dest = 1024;//(3)對拷貝對象進行賦值

            source = 2048;//(4)對源對象進行賦值

       首先(2)中將source賦給dest,執行了深拷貝動作,其時dest和source的值是一樣的,都是int.MaxValue;(3)對dest進行修改,dest值變為1024,由於是深拷貝,因此不會運行source,source仍然是int.MaxValue;(4)對source進行了修改,同樣道理,dest仍然是1024,同時int.MaxValue的值也不變,仍然是2,147,483,647;只有source變成了2048。

       再考慮以下寫法

        struct Point

        {

            public int X;

            public int Y;

            public Point(int x, int y)

            {

                X = x;

                Y = y;

            }

        }

 

        Point source = new Point(10, 20);

        Point dest = source;

 

        dest.X = 20

     當dest.X屬性變成20後,source的X屬性仍然是10


2.         淺拷貝是指源對象與拷貝對象共用一份實體,僅僅是引用的變量不同(名稱不同)。對其中任何一個對象的改動都會影響另外一個對象。舉個例子,一個人一開始叫張三,後來改名叫李四了,可是還是同一個人,不管是張三缺胳膊少腿還是李四缺胳膊少腿,都是這個人倒霉。比較典型的就有Reference(引用)對象,如Class(類)。

考慮以下寫法

        class Point

        {

            public int X;

            public int Y;

            public Point(int x, int y)

            {

                X = x;

                Y = y;

            }

        }

 

        Point source = new Point(10, 20);

        Point dest = source;

   dest.X = 20;

由於Point現在是引用對象,因此Point dest=source的賦值動作實際上執行的是淺拷貝,最後的結果應該是source的X字段值也變成了20。即它們引用了同一個對象,僅僅是變量明source和dest不同而已。

3.         引用對象的淺拷貝原理

引用對象之間的賦值之所以執行的是淺拷貝動作,與引用對象的特性有關,一個引用對象一般來說由兩個部分組成

(1)一個具名的Handle,也就是我們所說的聲明(如變量)

(2)一個內部(不具名)的對象,也就是具名Handle的內部對象。它在Manged Heap(托管堆)中分配,一般由新增引用對象的New方法是進行創建 www.2cto.com

       如果這個內部對象已被創建,那麼具名的Handle就指向這個內部對象在Manged Heap中的地址,否則就是null(從某個方面來講,如果這個具名的handle可以被賦值為null,說明這是一個引用對象,當然不是絕對)。兩個引用對象如果進行賦值,它們僅僅是復制這個內部對象的地址,內部對象仍然是同一個,因此,源對象或拷貝對象的修改都會影響對方。這也就是淺拷貝

4.         引用對象如何進行深拷貝

由於引用對象的賦值僅僅是復制具名Handle(變量)指向的地址,因此要對引用對象進行深拷貝就要重新創建一份該對象的實例,並對該對象的字段進行逐一賦值,如以下寫法

        class Point

        {

            public int X;

            public int Y;

            public Point(int x, int y)

            {

                X = x;

                Y = y;

            }

        }

 

        Point source = new Point(10, 20);

        Point dest = new Point(source.X, source.Y);

        //或以下寫法

        //Point dest = new Point()

        //dest.X = source.X

   //dest.Y = source.Y

       其時,source和dest就是兩個互相獨立的對象了,兩者的修改都不會影響對方

 

5.一些需要注意的東西

       (1):String字符串對象是引用對象,但是很特殊,它表現的如值對象一樣,即對它進行賦值,分割,合並,並不是對原有的字符串進行操作,而是返回一個新的字符串對象

       (2):Array數組對象是引用對象,在進行賦值的時候,實際上返回的是源對象的另一份引用而已;因此如果要對數組對象進行真正的復制(深拷貝),那麼需要新建一份數組對象,然後將源數組的值逐一拷貝到目的對象中

 


摘自 雲懷空-abel

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved