c++ 赋值运算符重载
在c++中也提供了赋值运算符“=”的重载,其原理和深浅拷贝相同,都需要解决浅拷贝所带来的堆区内存重复释放的问题,那么我们来看看,怎么同赋值运算符重载来解决问题
上代码
#include<iostream>
#include<string>
using namespace std;
//赋值运算符重载
class person
{
public:
person(int age)//调用有参构造
{
m_Age=new int(age);//用指针接收
}
~person()
{
if (m_Age != NULL)//判断堆区是否有数据,避免清理空的堆区
{
delete m_Age;
m_Age = nullptr;
}
}
//使用赋值运算符重载来避免浅拷贝导致的堆区内存重复释放
person& operator=(person& p)//接收一个新对象的数据
{
if (m_Age != NULL)//判断对象的堆区是否有数值,若有先清空堆区
{
delete m_Age;
m_Age = nullptr;
}
//然后重新在堆区创建新的数据来进行深拷贝操作
m_Age = new int(*p.m_Age);//创建一个与传入对象的属性值同等大小的内存空间,所以需要解引用
return *this;//返回对象本身
//方便进行链式编程
}
int* m_Age;//在堆区创建数据
};
其中,这一部分就是赋值运算符重载的核心内容
//使用赋值运算符重载来避免浅拷贝导致的堆区内存重复释放
person& operator=(person& p)//接收一个新对象的数据
{
if (m_Age != NULL)//判断对象的堆区是否有数值,若有先清空堆区
{
delete m_Age;
m_Age = nullptr;
}
//然后重新在堆区创建新的数据来进行深拷贝操作
m_Age = new int(*p.m_Age);//创建一个与传入对象的属性值同等大小的内存空间,所以需要解引用
return *this;//返回对象本身
//方便进行链式编程
}
形参中和深浅拷贝相同,都需要传入另一个对象来完成赋值操作,当然,若写成全局函数,则需要传入两个对象。
由于在类内构造函数中,使用了有参构造函数来对成员属性初始化,并且是在堆区开辟空间来储存数据,所以在运算符重载函数过程中,需要先判断对象本身是否有在堆区开辟空间,若有,则需要先清空其所在堆区开辟的空间,否则会导致部分内存空间无用化,浪费空间。
然后就与深拷贝操作相当,需要重新开辟一个与赋值对象成员属性相等的内存空间,所以使用到了*p.m_Age;利用解引用的方式得到另一个对象成员属性的具体数值来开辟相等的内存空间。
开辟多一个新的内存空间来保存所被赋值的值,可以保证在进行析构函数的运行过程中不会导致同一快内存空间的重复释放,导致内存崩溃,也就是所谓的浅拷贝问题
最后返回对象本身,方便链式编程。
剩余代码
void test01()
{
person p(18);
person p1(20);
person p2(30);
p2=p1 = p;
cout << "p的年龄为" << *p.m_Age << endl;//由于需要读取值,所以需要解引用
cout << "p1的年龄为" << *p1.m_Age << endl;
cout << "p2的年龄为" << *p2.m_Age << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
其中
p2=p1=p;的运算符重载中
若在赋值运算符重载中不返回*this,也就是对象本身,且不用&引用接收,将无法完成这样的链式操作,和左移运算符相似