【Linux】拷贝构造函数和赋值运算符重载函数

拷贝构造函数

一、作用
拷贝构造函数函数是将已存在对象生成相同类型的新对象。
二、原型
拷贝构造函数形参一定要有引用。有两个原因:

  • 避免递归构造的形参对象发生栈溢出
  • 节省对象销毁的开销
class CGoods
{
public:
	CGoods()//构造函数
	{
		mname = new char[1]();
		std::cout << "CGoods::CGoods()" << std::endl;
	}
	CGoods(float price)
	{
		mname = new char[1];
		mprice = price;
		std::cout << "CGoods::CGoods(float)" << std::endl;
	}
	CGoods(char* name, int amount, float price)
	{
		mname = new char[strlen(name) + 1]();
		strcpy_s(mname, strlen(name) + 1, name);
		mamount = amount;
		mprice = price;
		std::cout << "CGoods::CGoods(char*,int,float)" << std::endl;
	}
	~CGoods()//资源的统一释放
	{
		delete[] mname;
		mname = NULL;
	}
private:
	char* mname;
	int mamount;
	float mprice;
};
int main()
{
	CGoods good1;//调用默认的构造函数
	CGoods good2(10.1);//调用带有一个float类型的构造函数
	CGoods good3("car1",10,45000);//调用带有三个参数的构造函数
}

以上是简单的构造析构函数。拷贝构造函数的生成,加入以下代码:

CGoods(const CGoods& rhs)
{
	mname = new char[strlen(rhs.mname) + 1]();
	strcpy_s(mname, strlen(rhs.mname) + 1,rhs.mname);
	mamount = rhs.mamount;
	mprice = rhs.mprice;
}

以上只是浅拷贝,如果类中的成员变量有指针就要进行深拷贝

赋值运算符重载函数

一、定义
系统提供自定义类型的赋值
二、作用

  • 提供对象赋值的方式
  • 拿已存在的对象赋值给相同的类型的已存在的对象

三、设计的步骤

  • 自赋值
  • 释放旧的其他资源
  • 开辟新的资源
  • 成员赋值
CGoods& operator = (const CGoods& rhs)
{
	if(this == &rhs)//自赋值
	{
		return;
	}
	delete[] mname;
	mname = new char[strlen(rhs.mname) + 1]();
	strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);
	mamount = rhs.mamount;
	mprice = rhs.mprice;
	std::cout << "CGoods::operator=(const CGoods&)" <<std::endl;
	return *this;
}

四、赋值运算符的重载函数的返回值
1、返回值为void

void operator = (const CGoods& rhs)
{
	if(this == &rhs)//自赋值
	{
		return;
	}

	delete[] mname;
	mname = new char[strlen(rhs.mname) + 1]();
	strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);
	mamount = rhs.mamount;
	mprice = rhs.mprice;
	std::cout << "CGoods::operator=(const CGoods&)" <<std::endl;
}
int main()
{
	CGoods good1;
	CGoods good2;
	CGoods good3("car3", 10, 100000);
	goodl = good2 = good3;//连续赋值
	return 0;
}

我们将上述代码中的连续赋值这一块做以下分析:

  • 首先这句连续赋值的语句先处理good2 = good3
  • 就相当于good2调用了opreator这个赋值运算符的函数,然后将goo3当成实参传递进去。如:good2.operator = (good3);
  • 由于函数头为void定义,所以函数没有返回值,就相当于good1 = void(void没有返回值,相当于等于0)
  • 所以这句会出错

所以为了实现连续赋值,函数的返回值不能是void.
我们将函数的返回值改为类类型和类类型的引用
2、返回值为CGoods

CGoods operator = (const CGoods& rhs)
{
	if(this == &rhs)//自赋值
	{
		return;
	}

	delete[] mname;
	mname = new char[strlen(rhs.mname) + 1]();
	strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);
	mamount = rhs.mamount;
	mprice = rhs.mprice;
	std::cout << "CGoods::operator=(const CGoods&)" <<std::endl;
	return *this;
}

分析如下:

  • 还是先处理good2 = good3
  • 就相当于good2调用了opreator这个赋值运算符的函数,然后将goo3当成实参传递进去。如:good2.operator = (good3);
  • 他返回的是临时对象,临时对象就相当于good2对象的备份。
  • 我们发现将good1赋值给临时对象是成功的
  • 但是假设我们的赋值语句是:(good1 = good2) = good3;,他做的事情是将good1.operator = (good2)
  • 最后的结果成了将good3的值赋值给了临时对象。违背了原语句的意思。
  • 所以这种方法也是不可取的 。

3、返回值为CGoods&

CGoods& operator = (const CGoods& rhs)
{
	if(this == &rhs)//自赋值
	{
		return;
	}

	delete[] mname;
	mname = new char[strlen(rhs.mname) + 1]();
	strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);
	mamount = rhs.mamount;
	mprice = rhs.mprice;
	std::cout << "CGoods::operator=(const CGoods&)" <<std::endl;
	return *this;
}

由于返回的是引用,引用是一个别名,所以就是good2本身。
所以一般写赋值构造函数时返回的是类类型的引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值