一、什么是深浅拷贝?
浅拷贝:编译器自己创建的直接赋值
深拷贝:我们自己在堆区重新开辟空间进行赋值
二、使用浅拷贝会出现什么问题?
一旦有数据开辟在堆区,再使用浅拷贝,就会造成堆区内存重复释放,进行了非法操作
假如没有堆区数据
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout<<"Person的默认构造函数调用"<<endl;
}
Person(int age)
{
cout<<"有参构造函数!"<<endl;
m_age=age;
}
Person()
{
cout<<"Person的析构函数调用"<<endl;
}
int m_age;
} ;
void test01()
{
Person p1(18);
Person p2(p1);
cout<<"p1的年龄:"<<p1.m_age<<endl;
cout<<"p2的年龄:"<<p2.m_age<<endl;
}
int main()
{
test01();
system("pause");
return 0;
}
现在数据是完全正确的
那么我们下面加入堆区数据
m_Height=new int(height);
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout<<"Person的默认构造函数调用"<<endl;
}
Person(int age,int height)
{
cout<<"有参构造函数!"<<endl;
m_age=age;
m_Height=new int(height);
}
~Person()
{
//析构函数,将堆区的数据释放干净
if(m_Height!=NULL)
{
delete m_Height;
m_Height=NULL;
}
cout<<"Person的析构函数调用"<<endl;
}
int m_age;
int* m_Height;
} ;
void test01()
{
Person p1(18,180);
Person p2(p1);
cout<<"p1的年龄:"<<p1.m_age<<"身高为:"<<*p1.m_Height<<endl;
cout<<"p2的年龄:"<<p2.m_age<<"身高为:"<<*p2.m_Height<<endl;
}
int main()
{
test01();
system("pause");
return 0;
}
编译器就会报错
三、原因
如果使用浅拷贝,那么拷贝前后指向了堆区的同一块内存地址,按照先创建的后析构原则,p2通过拷贝构造被创建,他会先被释放,使用delete之后,0x0011的堆区内存已经被释放,p1调用析构函数的时候,发生了重复释放堆区内存,进行了非法操作
四、解决
解决浅拷贝的问题,就要使用深拷贝,在堆区重新开辟一块新的内存
Person(const Person&p)
{
cout<<"拷贝构造函数!"<<endl;
m_age=p.m_age;
m_height=new int(*p.m_height);
}
这样的话,在释放的时候,就会p1释放0x0011,p2释放0x0022,就不会出现重复释放的问题了
附上全部代码
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout<<"Person的无参构造函数调用"<<endl;
}
Person(int age,int height)
{
cout<<"有参构造函数!"<<endl;
m_age=age;
m_height=new int(height);//new表示新建一个对象
}
Person(const Person&p)
{
cout<<"拷贝构造函数!"<<endl;
m_age=p.m_age;
m_height=new int(*p.m_height);
}
~Person()
{
cout<<"Person的析构函数调用"<<endl;
if(m_height!=NULL)
{
delete m_height;
}
}
int m_age;
int* m_height;
} ;
void test01()
{
Person p1(18,180);
Person p2(p1);
cout<<"p1的年龄:"<<p1.m_age<<"身高:"<<*p1.m_height<<endl;
cout<<"p2的年龄:"<<p2.m_age<<"身高:"<<*p2.m_height<<endl;
}
int main()
{
test01();
system("pause");
return 0;
}