记录C++类和对象学习情况中:
C++赋值运算符重载的报错问题(涉及深拷贝和浅拷贝)
创建类:
class Person
{
public:
Person(int age)
{
m_age = new int(age)//2.传进age 用new int(age)把指针创建在堆区
}
int *m_age//1.创建age(年龄)用指针的形式表示,把真实的数据开辟到堆区(程序员自己开辟的空间)
};
写出析构函数:
//堆区由程序员手动开辟,需要程序员手动释放!!
//因此要在执行完后通过析构函数进行手动释放
~Person()
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
}
创建测试案例:
void test()
{
Person p1(18);
Person p2(20);
Person p3(22);
p3 = p2 = p1;//赋值操作
cout << "p1 = " << *p1.m_age << endl;
cout << "p2 = " << *p2.m_age << endl;
cout << "p3 = " << *p3.m_age << endl;
}
将以上代码执行进行赋值操作后会发现程序崩溃!!
问题:在赋值的过程中重复释放了堆区的内存。(简单得说就是同一处内存释放了两遍)
原因:函数进行p1 =p2拷贝时,编译器会进行浅拷贝,如下图所示,意味着p1和p2都是指向中间这一内存区。(p2先执行完再到p1)当p2执行完后会释放这一堆区内存,然后p1又执行完,会再次释放这一内存,造成了重复释放堆区内存的问题。
解决办法:
不用编译器的浅拷贝,自己写一份深拷贝。(赋值时给p2开辟一个新内存让p2存到新内存中)
Person& operator=(Person &p)//不是Person operator=(Person &p),
{
//系统自己实现的浅拷贝: m_age = age;
//我们写的深拷贝:
//1.先把age释放干净
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
//2.重新创建一块空间
m_age = new int(*p.m_age);
return *this;//this是指向自身的指针 *this接引用一下
}
完整代码:
#include<iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
m_age = new int(age);
}
Person& operator=(Person &p)
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
m_age = new int(*p.m_age);
return *this;
}
~Person()
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
}
int *m_age;
};
void test01()
{
Person p1(18);
Person p2(20);
Person p3(22);
p3 = p2 = p1;
cout << "p1 = " << *p1.m_age << endl;
cout << "p2 = " << *p2.m_age << endl;
cout << "p3 = " << *p3.m_age << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
输出结果:
以上。2023年2月17日22:46:11