1、淺層複製構造函數(利用默認的複製構造函數)
如果對象A的數據成員中有指針,那麼當我們把對象A複製給對象B的時候,此時對象A和對象B中的指針數據成員都是指向同一塊內存區域的,當兩個對象中的任意一個對象被刪除的時候,指針數據成員的那塊內存區域也會被刪除,因此另一個對象的成員指針變成了野指針,程序也會因此而崩潰。
class MyClass
{
public:
MyClass()
{
p = new int;
*p = 10;
}
~MyClass()
{
delete p;
p = NULL;
}
void set(int i)
{
*p = i;
}
int *getAdress()
{
return p;
}
private:
int *p;
};
int main()
{
//創建一個對象p
MyClass *p = new MyClass;
//調用默認的複製構造函數創建對象p1
MyClass p1(*p);
//兩個對象指針數據成員的地址是一樣的
cout<<"對象p的數據成員地址:"<<p->getAdress()<<endl;
cout<<"對象p1的數據成員地址:"<<p1.getAdress()<<endl;
//對象p改變了數據成員的值,p1成員的值也會被改變
p->set(999);
//刪除對象p,同時p1的指針成員也被刪除掉了,因爲他們指向的是同一塊內存地址
delete p;
//程序結束時崩潰
//因爲程序結束時會自動釋放p1,這時發現指針成員已經不存在了,做了一次重複的刪除,所以程序崩潰
return 0;
}
2、深層複製構造函數(自定義複製構造函數)
解決上述問題,需要顯式定義一個複製構造函數,在複製構造函數中爲成員指針分配新的內存空間,然後將舊對象成員的數據賦值給新對象成員,兩個對象的數據成員各自擁有不同的內存區域,因此不會相互影響,這種方式就叫做深層複製。
class MyClass
{
public:
MyClass()
{
p = new int;
*p = 10;
}
MyClass(const MyClass &m)
{
//申請一塊新的內存存放指針對象
p = new int;
*p = *(m.p);
}
~MyClass()
{
delete p;
p = NULL;
}
void set(int i)
{
*p = i;
}
int *getAdress()
{
return p;
}
private:
int *p;
};
int main()
{
//創建一個對象p
MyClass *p = new MyClass;
//調用默認的複製構造函數創建對象p1
MyClass p1(*p);
//兩個對象指針數據成員各自有用自己的內存區域
cout<<"對象p的數據成員地址:"<<p->getAdress()<<endl;
cout<<"對象p1的數據成員地址:"<<p1.getAdress()<<endl;
//對象p改變了數據成員的值,不會影響p1
p->set(999);
//刪除p,不會影響p1
delete p;
return 0;
}