【C++】了解赋值运算符重载函数

1、作用

这是我们拷贝构造函数的代码

class CGoods
{
public:
	
	//拷贝构造函数
	CGoods(const CGoods& rhs)
	{
		cout << this << ":CGoods::CGoods(CGoods )" << endl;
		_name = new char[strlen(rhs._name) + 1]();
		strcpy(_name, rhs._name);
		_price = rhs._price;
		_amount = rhs._amount;
	}

	CGoods(char* name, float price, int amount)
	{
		cout << this << ":CGoods::CGoods(char* , float , int )" << endl;
		_name = new char[strlen(name) + 1]();
		strcpy(_name, name);
		_price = price;
		_amount = amount;
	}
	//析构函数 
	~CGoods()
	{
		cout << this << ":~CGoods()" << endl;
		delete[] _name;
		_name = NULL;
	}
private:
	char* _name;
	float _price;
	int _amount;
};

int main()
{
	CGoods good1("good1", 500, 10);
	CGoods good2 = good1;
	return 0;
}

(2)如果我们在调用点添加下面两行代码,我们会认为是给 good1 重新赋值,运行是可以通过的,但是编译器并不知道自定义类型它是如何进行赋值的。

	CGoods good3;
	good3 = good2;

(3)针对上面的问题我们用赋值运算符重载函数,它的作用是用一个已存在的对象给另一个已存在的对象赋值。

2、特征

(1)有返回值,返回值是类类型的引用

(2)有自赋值的判断

它是为了避免有good2 = good2;`的存在,它是符合语法语义的,但是无意义,所以判断自赋值。
也就是判断 this 指针所指向的对象是不是与 rhs 相同的地址。

	CGoods& operator = (const CGoods& rhs)
	{
		if (this == &rhs)
		{
			return *this;
		}
		_name = rhs._name;
		_price = rhs._price;
		_amount = rhs._amount;
		return *this; 
	}
  • 浅拷贝
    但是程序崩溃了,这与拷贝构造函数的问题一样,是进行了浅拷贝,出现了野指针导致的函数崩溃。
    可以参考 拷贝构造函数
  • 深拷贝
    不能直接赋值,如果原本的对象已经有开辟的堆内存,如果直接赋值会导致原对象的堆内存找到指向,导致内存泄漏
    所以应该先释放原对象的内存,再开辟新内存。
CGoods& operator=(const CGoods& rhs)
	{
		if (this != &rhs)
		{
			delete[] _name;
			_name = new char[strlen(rhs._name) + 1];
			strcpy(_name, rhs._name);
			_price = rhs._price;
			_amount = rhs._amount;
		}
		return *this;
	}

3、临时对象

如果在调用点写一个这样的语句good3 = "good3";,我们认为它是无法运行的,因为前者是 CGoods 类型,后者是 char* 类型,两者类型不匹配。但是如果在类中有一个只有char类型参数的构造函数,能运行成功,为什么???
我们可以认为是用char
类型生成了一个临时对象后,使两者类型相同,然后再调用赋值运算符函数进行赋值。
所以临时对象的生存周期是在本条语句结束时就调用析构函数,释放内存。

class CGoods
{
public:
	CGoods()
	{
		cout << this << ":CGoods::CGoods()" << endl;
	}
	//拷贝构造函数
	CGoods(const CGoods& rhs)
	{
		cout << this << ":CGoods::CGoods(CGoods )" << endl;
		_name = new char[strlen(rhs._name) + 1]();
		strcpy(_name, rhs._name);
		_price = rhs._price;
		_amount = rhs._amount;
	}

	CGoods(char* name, float price, int amount)
	{
		cout << this << ":CGoods::CGoods(char* , float , int )" << endl;
		_name = new char[strlen(name) + 1]();
		strcpy(_name, name);
		_price = price;
		_amount = amount;
	}
	//赋值运算符重载函数
	CGoods& operator=(const CGoods& rhs)
	{
		cout << this << ":CGoods::operator = (CGoods)" << endl;
		if (this != &rhs)
		{
			delete[] _name;
			_name = new char[strlen(rhs._name) + 1];
			strcpy(_name, rhs._name);
			_price = rhs._price;
			_amount = rhs._amount;
		}
		return *this;
	}
	CGoods(char* name)
	{
		cout << this << ":CGoods::CGoods(char*)" << endl;
		_name = new char[strlen(name) + 1]();
		strcpy(_name, name);
	}
	//析构函数 
	~CGoods()
	{
		cout << this << ":~CGoods()" << endl;
		delete[] _name;
		_name = NULL;
	}
private:
	char* _name;
	float _price;
	int _amount;
};

int main()
{
	CGoods good1("good1", 500, 10);
	CGoods good2 = good1;
	CGoods good3;
	good1 = good2;
	cout << "-----------------------" << endl;
	good3 = "good3";
	cout << "-----------------------" << endl;
	return 0;
}

在这里插入图片描述
在这里插入图片描述

4、临时量

(1)内置类型(基本类型)产生的临时量是常量,存放在存储器中。
(2)自定义类型产生的临时量为变量,存放在内存中。
(3)隐式生成的临时量是常量,不能用普通引用来引用一个常量对象。
也就是实现good3 = "good3"; 时必须调用参数中带有const 的引用。
(4)显式生成的临时量是变量,可以用普通引用来引用。
也就是写成实现good3 = CGoods("good3"); ,就可以调用参数中没有const 的引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值