問題:在c++中如果沒有顯式定義拷貝建構函式,編譯系統會生成預設的拷貝建構函式,這種機制方便程式設計師編寫程式的同時也為程式設計師帶來了一些麻煩。當類中含有指標成員變數時,預設的拷貝建構函式會將拷貝函式的指標變數值賦給待拷貝建構函式的指標變數,使兩個指標變數指向同一片空間,物件銷毀時,析構函式就會釋放兩次動態分配的空間,從而造成錯誤。解決方案:
①深拷貝:當類的成員變數含有指標變數時,拷貝建構函式不應該再使用預設的拷貝建構函式,而應重新定義拷貝建構函式(開闢新空間,並將原始資料拷入新開闢的空間)從而避免在物件銷毀時產生對同一塊空間進行兩次釋放的錯誤。
②引用計數的寫時拷貝:此種解決方案不必在拷貝構造新物件時開闢新空間哦,而是在需要修改物件的記憶體空間資料時才開闢新空間並拷貝資料。
深拷貝:每一次拷貝構造時都直接開闢新的空間,並將資料拷入新的空間。避免銷毀物件呼叫析構函式時重複釋放同一片空間。
傳統寫法:
拷貝構造時自己開闢空間
//深拷貝傳統寫法
class string
string(const string& s)
~string()
string& operator=(const string& s)
return *this;
}private:
char* _
str;
};
現**法:
拷貝構造時借助建構函式等建立好記憶體空間後,交換各自的指標位址就可實現。
//深拷貝現**法
class string
string(const string& s)
:_str(null)
~string()
string& operator=(string s)
private:
char* _
str;
};
引用計數的寫時拷貝:記憶體連續實現;引用計數寫時拷貝的好處在於,如果拷貝出來的物件不需要改寫只需讀的話,就節省了開闢記憶體和資料複製的開銷。
//引用計數記憶體連續實現
class string
string(const string& s)
:_str(s._
str)
~string()
else
}string& operator=(string& s)
else
}return *this;
}private:
char* _
str;
};
記憶體分開實現:
//引用計數記憶體分開實現
class string
string(const string& s)
:_str(s._
str)
, _size(s._size)
~string()
else
}string& operator=(const string& s)
else
}return *this;
}char& operator(size_t pos)
return
_str[pos];
}private:
char* _
str;
int* _size;
};
總結:當類中含有指標變數成員時,應選擇深拷貝實現自定義的拷貝建構函式,不能再使用預設的拷貝建構函式,同時,利用引用計數的寫時拷貝對深拷貝進一步優化,如果拷貝構造出的物件不需要寫只需要讀時,就節省了開闢記憶體與複製資料的開銷。
C 解析深淺拷貝
首先我們看看淺拷貝。淺拷貝就是將物件中的所有字段複製到新物件中去,淺拷貝對於值型別和引用型別有不同的影響。值型別的值被複製到副本中後,修改副本中的值不會影響原來物件的值。然而引用型別被複製到副本中的是引用型別的引用。不是引用的物件。這樣再修改副本中的值是會導致原來物件的值也被修改了。但是這裡引用型別...
C 深淺拷貝
當結構體中沒有指標時,可進行淺拷貝,資料也會從乙個結構體拷貝到另乙個結構體 兩個結構體都存乙份資料 但當結構體中有指標的時候,假如使用使用淺拷貝,會使兩個結構體使用的指標都指向同乙個記憶體位址,在析構的時候會造成記憶體洩漏。深拷貝 需要對含有指標的結構體,使用 new 申請新的記憶體空間去儲存拷貝的...
c 深淺拷貝
對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。執行程式,螢幕輸出100。從以上 的執行結果可以看出,系統為物件b分配了記憶體並完成了與物件a的複製過程。就...