对堆区的数据进行赋值时为什么要重载等号运算符?
因为堆区的数据手动开辟,手动释放,在释放堆区的内存空间时,调用系统内的析构函数的话,会导致内存重复释放,导致程序崩溃,所以在赋值的时候的析构函数,需要我们自己来创建在堆区的地址,防止内存重复释放。
#include<iostream>//c++中标准的输入和输出流
using namespace std;//该语句的意思是使用标准的名空间
class person//定义一个类
{public://该类中所有的变量和属性都是public的,即公开的,
//那么在发生继承的时候,儿子所有从父类重继承的对象的属性也是公开的
//private是私有的意思
//protected是受保护的意思
person(int age)//person的构造函数
{
//在堆区开辟一块内存空间m_age
m_age = new int(age);
// 以age的这份数据重重新在内存当中开辟一片空间
//new int是用于在堆区开辟一块空间
//注意在堆区开辟的数据:手动开辟,手动释放
//new int返回的是指向该块内存区域的指针,
//我们只能通过这个返回来的这个指向堆区的指针去维护这块堆区
}
//自己创建的person的析构函数,因为对于在数据进行赋值的话,
//在调用系统内的析构函数的话,会导致内存重复释放,导致程序崩溃,
//所以在赋值的时候的析构函数,需要我们自己来创建在堆区的地址,防止内存重复释放
person& operator=(const person& p)
{//必须要以引用的方式传递
//因为引用的方式传递在内存中操控的是同一块内存区域
//而以局部变量的形式传递只是在内存中找另一块空间
//当被调函数返回到主函数时,局部变量的内存被释放了
//相当于没有操控这块内存而造成结果不对
if (m_age != NULL)
{
delete m_age;//如果这个指针不指向空的话,
//说明他在堆区维护着数据,所以需要我们将她在堆区的数据
//释放干净后,将她的指针指向为0 (防止野指针的出现),
//然后重新在堆区开辟一个内存空间,就可以防止在堆区内存的重复释放了
m_age = NULL;
}
//重新开辟一个内存空间:
//利用传进来的这个数据重新在堆区开辟一个空间
m_age = new int(*p.m_age);
//必须利用这个传进来的数据
//在堆区新开辟一块内存,否则内存就会重复释放,程序就会崩溃
return *this;//进行解引用的操作
//this指针可以用来返回类所指向的对象
//但是要进行解引用的操作才返回的是对象
//否则返回的是指向对象的地址
//this指针变量记录的是当前对象的内存地址,
//即this指针指向当前的对象
}
int *m_age;//注意这个是指向堆区的地址是一个指针,用于维护在堆区开辟的内存空间
};
void test01()
{
person p1(18);//有参构造函数
person p2(19);
person p3(20);
p1 = p2 = p3;//自定义数据的赋值需要我们在堆区重新开辟一块内存空间
cout << "p1的年龄为" << *p1.m_age << endl;//打印输出p1的年龄
cout << "p2的年龄为" << *p2.m_age << endl;//打印输出p2的年龄
cout << "p3的年龄为" << *p3.m_age << endl;//打印输出p3的年龄
//其中cout是c++中标准的输出流
//endl是换行的意思
}
int main(void)//主函数
{
test01();//调用函数
system("pause");
/*
system("PAUSE");和system("pause");作用和效果一样,因为dos命令是不区分大小写的。
system("PAUSE") 是暂停的意思,等待用户信号;不然控制台程序会一闪即过,你来不及看到执行结果。*/
return 0;//程序运行成功会返回一个0
}