<C++学习笔记>:赋值运算符的重载

117 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

1️⃣前言

今天的笔记内容是:

  • 赋值运算符的重载

在C++中,赋值运算符的使用很多,我们可以将类的对象A赋值给另一个对象B,相当于对象B拷贝了该类对象A的所有数据。

因此,我们自定义的类也应该有赋值运算。

与拷贝构造一样,C++编译器也会默认提供赋值运算符。

但我们要区别拷贝构造函数与赋值运算符的区别!

比如我们定义了一个类:myClass

然后操作如下:

image.png

拷贝构造函数起到一个初始化的作用。

当类对象已经存在时,使用赋值运算符可以进行赋值操作。

我们之前在学到拷贝构造函数时,提到浅拷贝和深拷贝的问题。

同样的,当值复制解决不了问题时(即浅拷贝不合适时),我们应该提供赋值运算符的重载。


2️⃣赋值运算符重载

示例

#include <iostream>
#pragma warning (disable: 4996)
using namespace std;
class Person {
public:
	//无参构造函数
	Person() {
		m_name = nullptr;
	}
	//有参构造函数
	Person(const char* p) {
		copyName(p);
	}
	//拷贝构造函数
	Person(Person& m) {
		copyName(m.m_name);
	}
	//析构函数
	~Person() {
		deleteName();
	}
	//赋值运算符的重载
	Person& operator=(Person& m) {
		deleteName();
		copyName(m.m_name);
		return *this;
	}
	//输出类对象的名字
	void show() {
		if (this->m_name)
			cout << "名字为:" << m_name << endl;
		else
			cout << "对象无名字!" << endl;
	}
protected:
	char* m_name;
	void copyName(const char* p);
	void deleteName();
};
void Person::copyName(const char* p)
{
	m_name = new char[strlen(p) + 1];
	if (m_name) {
		strcpy(m_name, p);
	}
}

void Person::deleteName()
{
	if (m_name) {
		delete m_name;
		m_name = nullptr;
	}
}

int main() {
	Person x("张三");
	cout << "x";
	x.show();
	Person y;
	cout << "y";
	y.show();
	y = x;  //赋值操作
	cout << "y";
	y.show();
	return 0;
}

运行结果为:

image.png

解析

首先可以看到,Person类的构造函数是在堆中申请,分配空间来存储人的名字的。

那么这个时候就存在浅拷贝的问题。

因此我们需要自定义拷贝构造函数和赋值运算符的重载函数

image.png

如上所示,重载的函数名是operator=,返回值是类对象的引用,而参数也是类对象的引用。

在函数体中,有三部分:

  1. 第一部分和析构函数类似,先将对象占用的资源释放掉
  2. 接着是重新分配新的空间资源,这与拷贝构造函数类似
  3. 最后返回类对象的引用

有个点注意一下:

  • 问题:为什么拷贝构造函数不需要调用deleteName()?
  • 解析:因为对象刚创建时,并没有分配存放名字的堆资源

3️⃣写在最后

好了,今天的笔记就到这里,欢迎大家到评论区一起讨论!