#include <iostream>
#include <cstring>
using namespace std;
/*
浅拷贝和深拷贝区别
1.浅拷贝,若类中不存在拷贝构造函数,会提供默认拷贝构造函数(浅拷贝),可以进行对象值赋值;
但当数据成员中存在需要在堆区申请空间时,析构时浅拷贝会造成空间双重释放问题;
2.深拷贝,当数据成员中存在需要在堆区申请空间时,会调用深拷贝,重新申请新的空间,可以避免析构时堆区空间被多次释放问题;
*/
class Person{
public:
Person(int age, char* str)
{
cout<<"person构造函数"<<endl;
m_age = age;
int len = strlen(str);
m_pName = new char[len+1];
strcpy(m_pName, str);
cout<<"age:"<<m_age<<","<<"name:"<<m_pName<<endl;
}
~Person()
{
if (m_pName != NULL)
{
cout<<"Person析构函数"<<endl;
std::cout<<m_pName<<std::endl;
delete m_pName;
m_pName = NULL;
}
}
private:
int m_age;
char *m_pName;
};
void test()
{
char str[100]="zhangsan";
Person per(20, str);
Person per1(per);//使用小括号法进行拷贝, free(): double free detected in tcache 2
}
int main()
{
test();
return 0;
}
执行时,会报错,因为m_pName堆区空间被两次释放,浅拷贝时直接将per成员的m_age和m_pName值赋值给per1的成员,per和per1的m_pName指向同一个空间,对象生命周期接收时,先释放per1对象m_pName空间,再次释放per的m_pName空间,导致多次释放报错;
#include <iostream>
using namespace std;
class Person{
public:
Person(int age, char* str)
{
cout<<"person构造函数"<<endl;
m_age = age;
int len = strlen(str);
m_pName = new char[len+1];
strcpy(m_pName, str);
cout<<"age:"<<m_age<<","<<"name:"<<m_pName<<endl;
}
//深拷贝
Person(const Person &per)
{
m_age = per.m_age;
int len = strlen(per.m_pName);
m_pName = new char[len+1];
strcpy(m_pName, per.m_pName);
cout<<"Person拷贝构造函数"<<endl;
}
~Person()
{
if (m_pName != NULL)
{
delete m_pName;
m_pName = NULL;
}
cout<<"Person析构函数"<<endl;
}
private:
int m_age;
char *m_pName;
};
void test()
{
char str[100]="zhangsan";
Person per(20, str);
Person per1(per);//使用小括号法进行拷贝
}
int main()
{
test();
return 0;
}
正常释放空间,因为Person per1(per),会调用深拷贝构造函数,per1中的m_pName成员在堆区重新申请了空间,per和per1对象的m_pName都有各自的空间,析构时释放的也是自己的空间,不会造成多处释放或未释放问题;