本文主要介绍为什么使用赋值运算符重载函数以及如何正确使用赋值运算符重载函数的方法。
1.原因
我们在使用类的时候,并不需要为该类重载 ‘=’ 运算符,因为编译器会为每个类提供了默认的赋值运算符‘=’,当我们使用这个默认的赋值运算符‘=’操作类对象时,该运算符会把这个类的所有数据成员都进行一次赋值操作。如下列代码所示:
#include <iostream>
using namespace std;
class Person
{
friend void test01();
public:
Person(int age)
{
m_Age = new int(age); //构造函数,进行初始化,将age变量放在堆区,
//并用m_Age指针变量进行维护
}
private:
int *m_Age;
};
void test01()
{
Person p1(10);
Person p2(20);
p2 = p1; //将p1的年龄值赋值给p2
cout << "p2的年龄是:" << *p2.m_Age << endl; //输出p2年龄的值
}
int main()
{
test01();
return 0;
}
编译并执行上述代码,结果如下:
由编译器输出的结果可以知道,使用系统默认的赋值运算符’=‘,可以将p2对象中的所有数据成员与p1对象中的所有数据成员相同,赋值运算符可以正常使用。
但是,在下面的示例中,当自己写好析构函数,释放m_Age指针后,再使用编译器默认的赋值运算符’=‘,则会出现报错情况。示例代码如下:
#include <iostream>
using namespace std;
class Person
{
friend void test01();
public:
Person(int age)
{
m_Age = new int(age); //构造函数,进行初始化,将age变量放在堆区,
//并用m_Age指针变量进行维护
}
private:
int *m_Age;
//析构函数
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
};
void test01()
{
Person p1(10);
Person p2(20);
p2 = p1;
cout << "p2的年龄是:" << *p2.m_Age << endl;
}
int main()
{
test01();
return 0;
}
编译并执行上述代码,结果如下:
上述错误信息表明:当对象 p1 和 p2 进行析构时,由于重复释放了同一块内存空间,导致程序崩溃报错。在这种情况下,就需要我们重载赋值运算符'='了。
2.示例代码
修改一下前面出错的示例代码,编写一个包含重载赋值运算符函数的类,修改后的代码内容如下:
#include <iostream>
using namespace std;
class Person
{
friend void test01();
public:
Person(int age)
{
m_Age = new int(age); //构造函数,进行初始化,将age变量放在堆区,
//并用m_Age指针变量进行维护
}
private:
int *m_Age;
//析构函数
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
//重载赋值运算符=
Person& operator=(Person& p)
{
//编译器提供的是浅拷贝
//m_Age=p.m_Age;
//应当先判断是否有属性在堆区,如果有,则应当先释放干净,再进行深度拷贝
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//创建新的堆区,并将新建的堆区地址指向m_Age
m_Age = new int(*p.m_Age);
//返回对象本身
return *this;
}
};
void test01()
{
Person p1(10);
Person p2(20);
Person p3(30);
p3=p2 = p1;
cout << "p1的年龄是:" << *p1.m_Age << endl;
cout << "p2的年龄是:" << *p2.m_Age << endl;
cout << "p3的年龄是:" << *p3.m_Age << endl;
}
int main()
{
test01();
return 0;
}
编译并运行上述代码,结果如下:
上述结果表明:
利用赋值运算符重载函数,解决了对象赋值时,析构函数多次释放同一块内存空间的问题。
3.总结
1.用类 A 类型的值为类 A 的对象赋值,且类 A 的数据成员中含有指针的情况下,必须显式提供赋值运算符重载函数。