当前位置: 首页 > article >正文

【C++】构造函数和析构函数第四部分(深拷贝和浅拷贝)--- 2023.11.25

目录

      • 什么是浅拷贝?
      • 浅拷贝的问题
      • 使用深拷贝解决浅拷贝问题
      • 结束语

什么是浅拷贝?

如果在一个类中没有人为定义拷贝函数,则系统会提供默认拷贝函数。那么在此默认拷贝函数中主要进行了简单的赋值操作,那这个简单的赋值操作我们一般叫做浅拷贝。

浅拷贝的问题

浅拷贝具体有什么问题,我们先看一个示例,如下所示:

class Student
{
public:
	Student(const char *name, int Age)
	{
		pName = (char*)malloc(strlen(name) + 1);
		strcpy(pName, name);
		age = Age;
	}

	~Student()
	{
		cout << "析构函数" <<endl;
		if (pName != NULL)
		{
			free(pName);
			pName = NULL;
		}
	}
public:
	char *pName;
	int age;
};

void test02()
{
	Student s1("小花", 18);
	Student s2(s1);

	cout << "s1 Name=" << s1.pName << " s1 age=" << s1.age << endl;
	cout << "s2 Name=" << s2.pName << " s2 age=" << s2.age << endl;
}

代码运行结果如下:
在这里插入图片描述

如上图所示,代码并不能正常运行,我们接下来分析原因。

Student s1("小花", 18);

首先我们先实例化对象,并且该对象名为s1,在实例化对象过程中会进行如下几步:

  1. 申请一块内存空间用来存放公有变量pName和age。
  2. 调用构造函数,在堆中申请一块内存空间,将指针name所指向的内容赋值给刚刚在堆中申请的内存空间,则该空间内容为“小花”
  3. 将Age赋值给age。
    最终如下所示:
    在这里插入图片描述
Student s2(s1);

当执行这条语句时,会调用拷贝构造函数,但是我们在类中并没有设定拷贝构造,故会调用系统默认的拷贝构造函数,即浅拷贝。即s2.pName = s1.pName,s2.age = s1.age。如下图所示:
在这里插入图片描述

此时当执行完test02函数时,会调用s1的析构函数和s2的析构函数。我们接下来分析下:


调用s1的析构函数时,会判断pName指向的空间存不存在,如果存在,即释放掉该空间,并将pName指针指向空。同样的操作,当执行s2的析构函数时,也会判断pName指向的空间存不存在,如果存在,则释放掉该空间,但是此时出现一个问题,pName指向的那块空间在执行s1析构函数时已经释放掉了,即再次释放空间时,会出现错误。这就是浅拷贝的问题,也是上述代码没有正常运行的根本原因(同一块空间被释放两次)。


使用深拷贝解决浅拷贝问题

在之前的示例中因为我们没有人为定义拷贝构造函数,使得自动调用了系统的默认拷贝构造函数,才造成同一块内存空间被同时释放两次的现象。那么为了解决这个问题,我们可以通过自己写拷贝构造函数来解决这个问题。

先上代码:

//深拷贝
	Student(const Student &stu)
	{
		cout << "自己的拷贝构造函数" << endl;
		//1.申请空间
		pName = (char*)malloc(strlen(stu.pName) + 1);
		//2.拷贝数据
		strcpy(pName, stu.pName);
		age = stu.age;
	}

在这里插入图片描述

运行代码结果如下:
在这里插入图片描述

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!


http://www.kler.cn/news/149124.html

相关文章:

  • Spring Boot 3 + Spring Security 6 最新版本修改 Json 登录后 RememberMe 功能问题失效的解决方案
  • NextJS开发:封装shadcn/ui中的AlertDialog确认对话框
  • windows系统mobaxterm远程执行linux上ssh命令
  • 中伟视界:AI智能分析盒子的人数统计AI算法通过什么算法模型可以解决重复统计的问题?
  • 【AI考证笔记】NO.1人工智能的基础概念
  • Mysql更新Blob存储的Josn数据
  • c++调用openssl对文件加解密
  • ubuntu配置免密登录vscode
  • 如何优化 Elasticsearch 查询性能
  • 华为P40无法链接adb的解决记录
  • 深度学习之六(自编码器--Autoencoder)
  • 面向植保任务的无人机集群系统及其应用研究
  • shell编程系列(4)-循环结构
  • Java第十二篇:连接安全版kafka(Kerberos认证)出现的问题解答
  • C++学习之路(十)C++ 用Qt5实现一个工具箱(增加一个时间戳转换功能)- 示例代码拆分讲解
  • Matlab 点云曲率计算(之二)
  • 浅谈现代化城市建设中智慧消防的研究与应用
  • Python与微信交互(互动)神器yyds
  • 数字乡村:科技赋能农村产业升级
  • 计算机毕业设计|基于SpringBoot+MyBatis框架的电脑商城的设计与实现(用户上传头像+用户收货管理)
  • 鸿运主动安全监控云平台存在任意文件读取漏洞 附POC
  • oracle免费资源 终止实例 以及新建一台实例的折腾记录
  • 【Linux进阶之路】进程间通信
  • ubuntu vmware开启3d加速画面异常
  • Unity 接入TapADN播放广告时闪退 LZ4JavaSafeCompressor
  • map出现遍历新数组undefined解决
  • C#鼠标穿透功能(WinForm)
  • 命令模式 (Command Pattern)
  • OPENWRT路由配置IPV6公网访问
  • PTA:用函数实现从数列中删除一个数