一個引用對象一般來說由兩個部分組成:一個具名的Handle,也就是我們所說的聲明(如變數)和一個內部(不具名)的對象,也就是具名Handle的內部對象。它在Manged Heap(託管堆)中分配,一般由新增引用對象的New方法是進行創建。深拷貝是指源對象與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。舉個例子,一個人名叫張三,後來用他克隆(假設法律允許)了另外一個人,叫李四,不管是張三缺胳膊少腿還是李四缺胳膊少腿都不會影響另外一個人。比較典型的就是Value(值)對象,如預定義類型Int32,Double,以及結構(struct),枚舉(Enum)等。
基本介紹
- 中文名:深拷貝
- 外文名:deep copy
- 學科:軟體工程
- 特點:源對象與拷貝對象互相獨立
- 要求:複製對象空間和資源
- 有關術語:拷貝構造函式
簡介,構造函式,拷貝構造函式,代碼示例,
簡介
如果在類中沒有顯式地聲明一個拷貝構造函式,那么,編譯器將會自動生成一個默認的拷貝構造函式,該構造函式完成對象之間的位拷貝。位拷貝又稱淺拷貝,淺拷貝會帶來數據安全方面的隱患。在進行賦值之前,為指針類型的數據成員另闢了一個獨立的記憶體空間,實現真正內容上的拷貝。這種拷貝稱為深拷貝。深拷貝有兩種方式實現:層層clone的方法和利用串列化來做深拷貝。層層clone的方法:在淺拷貝的基礎上實現,給引用類型的屬性添加克隆方法,並且在拷貝的時候也實現引用類型的拷貝。此種方法由於要在多個地方實現拷貝方法,可能會造成混論。利用串列化來做深拷貝:為避免複雜對象中使用clone方法可能帶來的換亂,可以使用串化來實現深拷貝。先將對象寫到流里,然後再重流里讀出來。
構造函式
在C+ +面向對象程式設計中,通過構造函式對對象進行初始化,它可以為對象在計算機記憶體中開闢記憶體空間,也可以為對象的數據成員提供初始值。構造函式是一個與類同名,沒有返回值的特殊成員函式,每當創建一個對象時(包括使用new動態創建對象),編譯系統就會自動調用構造函式。構造函式象類以外的一般函式和類成員函式一樣可以重載和帶預設參數,構造函式的重載為對象的生成提供了各種靈活的手段。構造函式分為預設構造函式(默認構造函式)和用戶自定義構造函式。當程式設計師沒有定義構造函式時,系統會提供一個無參的預設構造函式。如果用戶自定義了一個構造函式,編譯器提供的預設構造函式就自動消失了。
拷貝構造函式
拷貝構造函式的功能是用一個已有的對象來初始化一個被創建的同類的對象,是一種特殊的構造函式,具有一般構造函式的所有特性,其形參是本類對象的引用。用戶可以根據自己實際問題的需要定義特定的拷貝構造函式,以實現同類對象之間數據成員的傳遞。如果用戶沒有聲明類的拷貝構造函式,系統就會自動生成一個預設拷貝構造函式,這個預設拷貝構造函式的功能是把初始對象的每個數據成員的值都複製到新建立的對象中。拷貝構造函式的聲明形式為:類名(類名&對象名);下面定義了一個cat類和cat類的拷貝構造函式:
class cat{ private: int age; float weight; char* color; public: cat(); cat(cat&); void play(); void hunt();};cat::cat(cat&other){ age= other.age; weight= other.weight; color= other.color;}
調用拷貝構造函式有以下三種情況:
(1)用類的一個對象去初始化另一個對象時。
cat cat1;
cat cat2(cat1); //創建cat2時系統自動調用拷貝構造函式,用cat1初始化cat2。
(2)對象作為函式參數傳遞時,調用拷貝構造函式。
f(cat a){} //定義f函式,形參為cat類對象cat b; //定義對象b
f(b);//進行f函式調用時,系統自動調用拷貝構造函式
(3)如果函式的返回值是類的對象,函式調用返回時,調用拷貝構造函式。
cat f() //定義f函式,函式的返回值為cat類的對象
{cat a; …return a;}
cat b;//定義對象b
b= f();//調用f函式,系統自動調用拷貝構造函式
代碼示例
public static void main(String[] args) { TestClass aaa = new TestClass("yanjun", 23); aaa.getCat().setColor("red"); aaa.getCat().setSize(23); TestClass bbb = (TestClass) aaa.clone(); aaa.setName("new yanjun"); aaa.setAge(18); aaa.getCat().setColor("blue"); aaa.getCat().setSize(18); System.out.println(aaa.getName() + "--------" + bbb.getName()); //輸出new yanjun--------yanjun System.out.println(aaa.getAge() + "--------" + bbb.getAge());//輸出18--------23 System.out.println(aaa.getCat().getColor() + "--------" + bbb.getCat().getColor());//輸出blue--------red System.out.println(aaa.getCat().getSize() + "--------" + bbb.getCat().getSize());//輸出18--------23}class TestClass implements Cloneable{ private String name; private int age; private Cat cat; public TestClass(String name, int age){ this.name = name; this.age = age; this.cat = new Cat(); } //省去get和set方法 public Object clone(){ TestClass o=null; try{ o=(TestClass)super.clone();//Object 中的clone()識別出你要複製的是哪一個對象。 } catch(CloneNotSupportedException e){ System.out.println(e.toString()); } o.cat = (Cat)o.cat.clone(); return o; } }class Cat{ private String color; private int size; //省去get和set方法 public Cat() { this.color = "red"; this.size = 23; } public Object clone(){ Object o=null; try{ o=(Cat)super.clone();//Object 中的clone()識別出你要複製的是哪一個對象。 } catch(CloneNotSupportedException e){ System.out.println(e.toString()); } return o; } }