一、拷貝構造函數的聲明
Array(const Array & arr);
二、拷貝構造函數的實現分為兩種,即是深拷貝和淺拷貝。
1.淺拷貝
代碼如下:
class Array
{
public:
Array()
{
m_iCount = 5;
m_pArr = new int[m_iCount];
}
Array(const Array& arr)
{
m_iCount = arr. m_iCount;
m_pArr = arr.m_pArr;
}
private:
int m_iCount;
int * m_pArr;
}
int main(void)
{
Array arr1;
Array arr2 = arr1;
return 0;
}
這種簡單的淺拷貝將會使arr1和arr2裡面的m_pArr成員的值是一樣的,即指向的內存地址是一樣的。如下圖所示。此時,如果先給arr1的m_pArr賦了一些值,也就是在內存地址0x00FF00這段內存中寫了一些值,然後再給arr2的m_pArr再賦值的時候,那麼同一段內存將會被重寫,而覆蓋掉之前arr1的m_pArr所賦進去的值。更嚴重的是當我們銷毀arr1這個對象的時候,我們為了避免內存洩露,肯定會釋放m_pArr所指向的這段內存。如果我們已經釋放掉了這段內存,再去銷毀arr2對象的時候,肯定也會以同樣的方式再釋放掉arr2裡面的m_pArr所指向的這段內存,這樣同一段內存將被釋放兩次,計算機會以崩潰的方式抗議,與語法錯誤的提示信息是不一樣的,難以查找出錯根源。
2.深拷貝
因此,我們希望拷貝構造函數所完成的工作是這樣的,如下圖所示。兩個對象的指針所指向的應該是不同的內存,拷貝的時候不應該是將指針的地址簡單地拷貝過來,而是將指針所指向的地址中存儲的每一個元素依次地拷貝過來,這個才是我們真正想要的效果,這個過程就是深拷貝。
代碼如下:
class Array
{
public:
Array()
{
m_iCount = 5;
m_pArr = new int[m_iCount];
}
Array(const Array& arr)
{
m_iCount = arr. m_iCount;
m_pArr = new int[m_iCount];
for(int i=0;i { m_pArr[i] = arr.m_pArr[i]; } //m_pArr = arr.m_pArr; } private: int m_iCount; int * m_pArr; } int main(void) { Array arr1; Array arr2 = arr1; return 0; } 3.總結: 當進行對象拷貝時,不是簡單地進行值得拷貝,而是將堆中內存的數據也進行拷貝,這種拷貝方式就叫做深拷貝,只進行值得拷貝的方式叫做淺拷貝。深淺拷貝具有以下特點: (1)當數據成員中含有指針時,淺拷貝會使兩個對象的成員指針指向相同的地址,這個時候會導致地址重復刪除或被重新賦值。 (2)不是所有的對象都需要深拷貝,應該根據情況合理使用。 (3)深拷貝不是簡單的值拷貝,而是重新分配同樣大小的內存地址,將指針成員指向的內存數據進行拷貝。