浅拷贝
我们先创建一个Computer类,头文件Computer.h 代码如下
class Computer
{
private:
char *_brand;
float _price;
public:
void setBrand(const char* brand){
strcpy(_brand,brand);
}
void setPrice(float price){
_price=price;
}
void print(){
cout<<" brand :"<<_brand<<endl
<<" price :"<<_price<<endl;
}
Computer(const char* brand,float price);
Computer(const char* brand);
Computer(const Computer& rhs);
~Computer();
};
我们可以看到其成员变量有一个字符指针 _brand,在创建对象的过程中指向堆空间的内容,Computer.cc文件包含其构造函数,析构函数
//析构函数
Computer::~Computer(){
cout<<"~Computer"<<endl;
/* if(_brand != nullptr) */
if(_brand)
{
/* cout << "delete [] _brand" << endl; */
delete [] _brand;
_brand = nullptr;
}
}
//构造函数
Computer::Computer(const char* brand,float price)
:_brand(new char[strlen(brand)+1]())
,_price(price)
{
strcpy(_brand,brand);
_price=price;
}
//构造函数
Computer::Computer(const char* brand)
//初始化列表
:_price(0)
{
strcpy(_brand,brand);
}
在测试过程(代码如下main.cc)中我们可以看到com1对象申请一块堆空间为“华硕”,我们又创建了一个对象com2与com1相等,此时com2的字符指针指向的和com1指向的是同一块堆空间的内容,所以在修改为“MAC”后打印出的com1和com2商标都为“MAC”。同时又因为在析构时com1释放了堆空间的内容,在析构com2时出现了报错。
void test(){
Computer com1("华硕",1000);
Computer com2=com1;
cout<<"com1"<<&com1<<endl;
cout<<"com2"<<&com2<<endl;
com2.setBrand("MAC");
com1.print();
com2.print();
}
int main(){
test();
return 0;
}
/*运行结果如下
Cp10x7fffffffde80
Cp30x7fffffffde90
brand :MAC
price :1000
brand :MAC
price :1000
~Computer
~Computer
free(): double free detected in tcache 2
*/
深拷贝
那么怎么样避免这种情况?去完全的拷贝对象的所有内容,这就是深拷贝。我们可以将默认拷贝构造函数进行修改如下,我们在拷贝的时候同时在堆空间中申请了一份空间,示例图如下
//浅拷贝如下示范
Computer::Computer(const Computer& rhs)
// :_brand(new char[strlen(rhs._brand)+1]())
:_brand(rhs._brand)
,_price(rhs._price)
{
// strcpy(_brand,rhs._brand);
}
//深拷贝如下
Computer::Computer(const Computer& rhs)
:_brand(new char[strlen(rhs._brand)+1]())
// :_brand(rhs._brand)
,_price(rhs._price)
{
strcpy(_brand,rhs._brand);
}