淺拷貝
一直以來,設計乙個類,個人認為,最能體現水平的地方在於:類中含有指標成員變數。
1 #include 2using
namespace
std;34
class
hasptrmem5
9 ~hasptrmem()
1014
15int*d;
16};
1718
intmain()
19 //
異常析構
定義了乙個含有指標成員變數d的型別hasptrmem。
該成員d在構造時會接受乙個new操作分配堆記憶體返回的指標,而在析構的時候則會被delete操作用於釋放分配的堆記憶體。
在main函式中,宣告了hasptrmem型別的物件a,又使用a初始化了物件b。
按照c++的語法,這會呼叫hasptrmem的拷貝建構函式。
而這裡的拷貝建構函式由編譯器隱式生成,其作用是執行類似於memcpy的按位拷貝。
這樣的構造方式有乙個問題,就是a.d和b.d都指向了同一塊堆記憶體。
因此在main作用域結束的時候,物件b和物件a的析構函式會分別依次被呼叫。
當其中之一完成析構之後(比如物件b先析構,b.d先被delete),那麼a.d就成了乙個「懸掛指標」(dangling pointer),因為其不再指向有效的記憶體了。
那麼在該懸掛指標上釋放記憶體就會造成嚴重的錯誤。
深拷貝通常情況下,在類中未宣告建構函式的情況下,c++也會為類生成乙個「淺拷貝」(shollow copy)的建構函式。
而最佳的解決方案是使用者自定義拷貝建構函式來實現「深拷貝」(deep copy),修正上例為深拷貝的結果:
1 #include 2using
namespace
std;34
class
hasptrmem
59 hasptrmem(const hasptrmem& h) : d(new
int(*h.d)) //
拷貝建構函式,從堆中分配記憶體,並用*h.d初始化
10 ~hasptrmem()
1115
16int*d;
17};
1819
intmain()
20 //
正常析構
為類hasptrmem新增了乙個拷貝建構函式。
拷貝建構函式從堆中分配新記憶體,將該分配來的記憶體的指標交還給d,又使用*(h.d)對*d進行了初始化。
通過這樣的方法,就避免了懸掛指標的困擾。
good good study, day day up.
順序 選擇 迴圈 總結
C 拷貝建構函式 深拷貝與淺拷貝
深拷貝函式主要是解決拷貝函式不能直接拷貝指標所指記憶體的資料的問題 其次,介紹一下什麼是拷貝建構函式以及拷貝建構函式將在何時被呼叫?拷貝建構函式是一種特殊的建構函式,其形參是本類物件的引用,其作用是使用乙個已經存在的物件來初始化 乙個新的同類的物件。何時被呼叫?當用類的物件去初始化另外乙個物件的時候...
C 淺拷貝與深拷貝建構函式
include using namespace std 淺拷貝和深拷貝區別 1.淺拷貝,若類中不存在拷貝建構函式,會提供預設拷貝建構函式 淺拷貝 可以進行物件值賦值 但當資料成員中存在需要在堆區申請空間時,析構時淺拷貝會造成空間雙重釋放問題 2.深拷貝,當資料成員中存在需要在堆區申請空間時,會呼叫深...
C 拷貝建構函式 深拷貝與淺拷貝 詳解
深拷貝和淺拷貝可以簡單理解為 如果乙個類擁有資源,當這個類的物件發生複製過程的時候,資源重新分配,這個過程就是深拷貝,反之,沒有重新分配資源,就是淺拷貝 對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在...