對於普通型別的物件來說,它們之間的複製是很簡單的,例如:
int a=88;
int b=a;
而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。
<
iostream
>
using
namespace
std;
class
cexample
void
show ()
;intmain()
執行程式,螢幕輸出100。從以上**的執行結果可以看出,系統為物件b分配了記憶體並完成了與物件a的複製過程。就類物件而言,相同型別的類物件是通過拷貝建構函式來完成整個複製過程的。下面舉例說明拷貝建構函式的工作過程。
<
iostream
>
using
namespace
std;
class
cexample
cexample(
const
cexample&c)
void
show ()
;intmain()
cexample
(const cexample
& c)就是我們自定義的拷貝建構函式。可見,拷貝建構函式是一種特殊的建構函式,函式的名稱必須和類名稱一致,它的唯一的乙個引數是本型別的乙個引用變數,該引數是const型別,不可變的。例如:類x的拷貝建構函式的形式為x(x& x)。
當用乙個已初始化過了的自定義類型別物件去初始化另乙個新構造的物件的時候,拷貝建構函式就會被自動呼叫。也就是說,當類的物件需要拷貝時,拷貝建構函式將會被呼叫。以下情況都會呼叫拷貝建構函式:
乙個物件以值傳遞的方式傳入函式體
乙個物件以值傳遞的方式從函式返回
乙個物件需要通過另外乙個物件進行初始化。
如果在類中沒有顯式地宣告乙個拷貝建構函式,那麼,編譯器將會自動生成乙個預設的拷貝建構函式,該建構函式完成物件之間的位拷貝。位拷貝又稱淺拷貝,後面將進行說明。
自定義拷貝建構函式是一種良好的程式設計風格,它可以阻止編譯器形成預設的拷貝建構函式,提高原始碼效率。
淺拷貝和深拷貝
在某些狀況下,類內成員變數需要動態開闢堆記憶體,如果實行位拷貝,也就是把物件裡的值完全複製給另乙個物件,如a=b。這時,如果b中有乙個成員變數指標已經申請了記憶體,那a中的那個成員變數也指向同一塊記憶體。這就出現了問題:當b把記憶體釋放了(如:析構),這時a內的指標就是野指標了,出現執行錯誤。
深拷貝和淺拷貝可以簡單理解為:如果乙個類擁有資源,當這個類的物件發生複製過程的時候,資源重新分配,這個過程就是深拷貝,反之,沒有重新分配資源,就是淺拷貝。下面舉個深拷貝的例子。
#include
using namespace std;
class ca
ca(const ca& c)
void show()
深拷貝和淺拷貝的定義可以簡單理解成:如果乙個類擁有資源(堆,或者是其它系統資源),當這個類的物件發生複製過程的時候,這個過程就可以叫做深拷貝,反之物件存在資源,但複製過程並未複製資源的情況視為淺拷貝。
淺拷貝資源後在釋放資源的時候會產生資源歸屬不清的情況導致程式執行出錯。
test(test &c_t)是自定義的拷貝建構函式,拷貝建構函式的名稱必須與類名稱一致,函式的形式引數是本型別的乙個引用變數,且必須是引用。
當用乙個已經初始化過了的自定義類型別物件去初始化另乙個新構造的物件的時候,拷貝建構函式就會被自動呼叫,如果你沒有自定義拷貝建構函式的時候,系統將會提供給乙個預設的拷貝建構函式來完成這個過程,上面**的複製核心語句就是通過test(test &c_t)拷貝建構函式內的p1=c_t.p1;語句完成的。
C 深拷貝 與 淺拷貝
最近在寫一些c 程式,遇到個問題,記憶體會出錯,查了一些材料,終於發現問題所在了,原來碰到了傳說中的深拷貝和淺拷貝問題了,檢視一些材料,現在對這個問題做個總結 在類定義中,預設是淺拷貝,即 位拷貝 用在基本類中或者一些沒有指標的自定義型別中沒有一點問題,但是當遇到含有指標變數的自定義型別的時候,就會...
C 淺拷貝與深拷貝
淺拷貝 shallow copy 指的是當物件的字段被拷貝的時候,字段應用的物件不會被拷貝。深拷貝是對物件例項當中的字段引用的物件也進行拷貝的一種方式。淺拷貝可以通過將類實現介面icloneable class myclass icloneable 舉個簡單的例項 using system usin...
c 淺拷貝與深拷貝
淺拷貝與深拷貝 像這樣的淺拷貝會導致程式崩潰,因為同乙個空間被釋放了兩次 include include using namespace std class s copy ostream operator class s copy s copy private char p ostream oper...