C++ 拷貝建構函式中淺拷貝與深拷貝
淺拷貝建構函式
看一段拷貝建構函式的程式碼
#include <iostream>
#include <cstring>
using namespace std;
class Array{
public :
Array(){
cout<<"Array()"<<endl;
}
Array(const Array &arr){ /// 拷貝建構函式
m_iCount = arr.m_iCount;
cout<<"Array &"<<endl;
}
virtual ~Array(){
cout<<"~Array()"<<endl;
}
void setCount(int _count){
m_iCount = _count;
}
int getCount(){
return m_iCount;
}
private :
int m_iCount;
};
int main(){
Array arr1;
arr1.setCount(5);
Array arr2(arr1);///淺拷貝
cout<<"arr2 m_iCount " <<arr2.getCount()<<endl;
return 0;
}
類Array例項化一個arr1的物件,並給資料成員m_iCount賦值為5。
接著類Array例項化一個物件arr2並將arr1的資料成員的值拷貝給arr2
執行程式碼,顯然arr1和arr2的資料成員m_iCount的值都為5,系統給arr1,arr2分配了記憶體空間並使得arr1的值複製給了arr2
接下來再看一段程式碼:
#include <iostream>
#include <cstring>
using namespace std;
class Array{
public :
Array(int _count){
m_iCount = _count;
m_pArr = new int[m_iCount];
cout<<"Array()"<<endl;
}
Array(const Array &arr){ /// 拷貝建構函式
m_iCount = arr.m_iCount;
m_pArr = arr.m_pArr; ///兩個指標指向同一塊記憶體
cout<<"Array &"<<endl;
}
virtual ~Array(){
delete []m_pArr;
m_pArr = NULL;
cout<<"~Array()"<<endl;
}
void setCount(int _count){
m_iCount = _count;
}
int getCount(){
return m_iCount;
}
void printAddr(){
cout<<"m_pArr : "<<m_pArr<<endl;
}
private :
int m_iCount;
int *m_pArr;
};
int main(){
Array arr1(5);
Array arr2(arr1);
arr1.printAddr();
arr2.printAddr();
return 0;
}
我們在類中新增一個數據成員int型的指標m_pArr,例項化一個物件arr1並給資料成員m_iCount賦值為5,與此同時系統也需要給另一個數據成員m_pArr在堆區分配記憶體空間
接著例項化一個物件arr2並將arr1的值複製給arr2,系統呼叫拷貝建構函式。將arr1.m_iCount賦值給arr2.m_iCount,將arr1.m_pArr賦值給arr2.m_iArr。因為在拷貝建構函式中,系統並沒有在堆區分配一個記憶體空間給arr2的資料成員m_iArr。所以這裡兩個物件的資料成員m_iArr顯然都指向了同一塊記憶體空間,那麼會有什麼問題呢?
當我們在呼叫解構函式,釋放記憶體空間的時候,兩個物件指向的那塊記憶體空間就會被釋放兩次,這樣程式會奔潰,導致出錯。
這就是淺拷貝帶來的危險
這裡再引入深拷貝:
Array(const Array &arr){ /// 拷貝建構函式
m_iCount = arr.m_iCount;
m_pArr = new int[m_iCount];
for(int i=0;i<m_iCount;i++) m_pArr[i]=arr.m_pArr[i];
cout<<"Array &"<<endl;
}
當類中存在資料成員需要動態開闢記憶體空間的時候,需要使用深拷貝的方式
區別:
在某些狀況下,類內成員變數需要動態開闢堆記憶體,如果實行位拷貝,也就是把物件裡的值完全複製給另一個物件,如A=B。這時,如果B中有一個成員變數指標已經申請了記憶體,那A中的那個成員變數也指向同一塊記憶體。這就出現了問題:當B把記憶體釋放了(如:析構),這時A內的指標就是野指標了,出現執行錯誤。
深拷貝和淺拷貝可以簡單理解為:如果一個類擁有資源,當這個類的物件發生複製過程的時候,資源重新分配,這個過程就是深拷貝,反之,沒有重新分配資源,就是淺拷貝。