在介紹C++淺拷貝與深拷貝之前,我們先引出C++的拷貝構造函數。 C++拷貝構造函數是一種特殊的構造函數,其形參是本類對象的引用。用於在建立一個新的對象時,使用一個已經存在的對象來初始化這個新對象。因為拷貝構造函數時特殊的構造函數,所以其沒有返回值類型,且名稱與類名相同;該函數只有一個參數,即此類對 ...
在介紹C++淺拷貝與深拷貝之前,我們先引出C++的拷貝構造函數。
C++拷貝構造函數是一種特殊的構造函數,其形參是本類對象的引用。用於在建立一個新的對象時,使用一個已經存在的對象來初始化這個新對象。因為拷貝構造函數時特殊的構造函數,所以其沒有返回值類型,且名稱與類名相同;該函數只有一個參數,即此類對象的引用;所有類都必須有一個拷貝構造函數,如果沒有自動以拷貝構造函數,系統會自動產生一個預設拷貝構造函數。
自定義拷貝構造函數的一般形式為:
類名::類名(const 類名& 對象名)
{
函數體;
}
淺拷貝:在進行初始化的過程中僅進行簡單的數據成員賦值。
例如:
class A{
private:
int a;
public:
A(int ta):a(ta){}
};
有如下代碼:
A a(5);
A b(a);
程式執行b(a)時,執行操作:b.a=a.a;與系統自動產生的拷貝構造函數:
A::A(const A& t){this->a=t.a;}
執行相同內容。完整代碼如下:
執行結果為:
從結果中我們發現,我們通過對象a初始化的對象b中,數據元素與a中完全相等,甚至指針指向的地址都相同。不難看出,在a初始化b過程中只是進行了簡單的值傳遞,並沒有為b中的p申請新的堆記憶體空間。即兩個對象的指針指向同一個地址,這也就意味著此地址將被釋放兩次,顯然是不可取的。這一點由輸出結果中b中*p的值異常便可看出。為瞭解決此問題,我們需要深拷貝。
深拷貝:當類中有指針類型元素,需要申請堆記憶體空間時,為新的指針分配新的記憶體空間。(不可進行簡單的值傳遞)
這時,需要我們自定義拷貝構造函數:
此時,重新編譯運行程式,結果為:
此時,雖然對象a已被刪除,對象a仍輸出正常,這是因為在自定義的深拷貝函數中,為新的對象申請了新的空間,而不是令其指向a中p指針變數指向的地址。
總結:
當類中無需申請動態資源時,淺拷貝構造函數可以很好的工作。當需要申請動態記憶體時,即類中有指針變數,則需要自定義深度拷貝函數。
表述不當之處,還望各路大神指正。