关于学习深拷贝和浅拷贝过程中的一些总结

最近在学习c++的基础知识,赋值运算符重载的这一章是以联系深拷贝和浅拷贝问题,作为知识的运用背景引入的。

首先涉及到深拷贝和浅拷贝问题的一个场景是:内部包括指针变量的对象的赋值,在下面的代码中,假如不重载赋值运算符和拷贝运算符 ,那么进行该对象的赋值以及拷贝操作时,就会进行浅拷贝,也就是其内部的指针进行的操作是m_Age = p.m_Age;,也就是两个变量的指针将指向同一块内存,而且之前m_Age 所指向的内存也没有得到释放,而当代码执行完,两个变量被释放就会导致同一块内存被释放两次,就会引发问题,因此需要以引入深拷贝这一做法。

但是代码中的一个问题让我有些困惑,就是重载赋值运算符的函数Person& operator=(Person &p)的返回值只能是Person&,如果改成Person的话,下面的p3 = p2 = p1; //赋值操作就会报错,给出的原因是如果是函数返回值是person的话,p2 = p1的结果会先创建一个临时对象,然后再将该临时对象赋值给p3,但我的疑惑在于什么情况下会生成临时对象,什么情况下会直接进行赋值呢,在下面的这段代码中,好像体现的是当Person& operator=(Person &p)的返回值是person(引用)的时候,就会直接赋值,而返回值是person的时候就会先创建一个临时对象,然后再将该临时对象赋值给p3

#include<iostream>
using namespace std;
 
class Person
{
public:

	Person(int age)
	{
		//将年龄数据开辟到堆区
		m_Age = new int(age);
	}

	Person(const Person& p) //设置拷贝构造函数为深拷贝,避免出现同一块内存被多次释放
	{
		//将年龄数据开辟到堆区
		m_Age = new int(*p.m_Age);
	}
	//重载赋值运算符 
	Person& operator=(const Person &p) //注意这里参数要用const修饰,以支持连续赋值操作
	{
		if (m_Age != NULL) //赋值之前若指针不为空,先释放该块内存
		{
			delete m_Age;
			m_Age = NULL;
		}
		//编译器提供的代码是浅拷贝
		//m_Age = p.m_Age;

		//提供深拷贝 解决浅拷贝的问题
		m_Age = new int(*p.m_Age); //这里的*p.m_Age是解引用,因为m_Age是指针。

		//返回自身
		return *this;
	}


	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}

	//年龄的指针
	int *m_Age;

};


void test01()
{
	Person p1(18);

	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();


	system("pause");

	return 0;
}

问了GPT之后得到的答案是下面这样的

当拷贝赋值函数返回的不是对象引用,而是返回对象本身(非引用类型),那么在每次赋值操作之后都会生成一个临时对象。这是因为如果拷贝赋值函数返回对象本身,那么函数返回值会通过拷贝构造函数构造的,而拷贝构造函数的调用会创建一个新的对象。这个临时对象在表达式求值完成后会被销毁。

那么总结来我这次遇到的问题:
1、如果要进行内部包括指针变量的对象的赋值,就要考虑深拷贝浅拷贝,具体做法就是重载赋值运算符和构造支持深拷贝的拷贝构造函数。

2.如果赋值运算符重载中’operator=` 要返回是引用,因为这样在连续赋值的过程中不会创建中间对象,不会增加性能开销。

3.在视频评论区发现了一条很有用的总结:当使用链式赋值,也就是连续多个变量连等赋值时,Person& operator=(Person &p)中的返回值和参数类型一致就不会报错,比如说改成Person operator=(Person p)就不会报错,因为返回值和参数类型一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值