【C++】基础语法:深浅拷贝

前言

在学习拷贝构造函数的时候遇到了深浅拷贝这个知识点 就写篇文章记录一下

(引用的部分不用太在意 是查的
(需要前提知识:知道默认拷贝构造函数是什么 知道默认拷贝构造函数和构造函数的关系、知道析构函数的写法和用处

浅拷贝

浅拷贝(Shallow Copy)是指创建一个新的对象,并将原始对象的非静态字段复制到新对象。如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的,则复制引用但不复制引用的对象。这意味着原始对象和复制对象引用同一个对象,所以任何对复制对象的修改都可能影响到原始对象。因此,浅拷贝操作后的两个对象共享同一个底层数据源。

简单来说就是 逐个字节拷贝
被拷贝以及拷贝对象它们的值是完全相同的

深拷贝

深拷贝(Deep Copy)则是指创建一个完全独立的新对象,并递归地复制原始对象及其所有子对象。这意味着无论对象的层级有多深,新对象和原对象都是完全独立的。修改其中一个对象不会影响另一个对象。深拷贝会复制对象的所有层级,包括对象的属性、嵌套对象、引用等。

一般来说 涉及到动态开辟的对象在拷贝的时候 都需要深拷贝

对比

我们借助一段代码来比较深浅拷贝的区别 以及为什么要存在深拷贝

为没学栈的同学解释一下:下面这段代码就是创建了两个对象s1 和s2 然后将1、2、3、4逐个存入s1中 调用了默认拷贝构造函数将s1拷贝给s2 并且用的是浅拷贝的方式

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (DataType*)malloc(capacity * sizeof(DataType));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity = capacity;
	}
	void Push(const DataType& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	size_t _size;
	size_t _capacity;
};
int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);
	Stack s2(s1);
	return 0;
}

下面是s1和s2中array数组首元素指针的存储情况
在这里插入图片描述
根据浅拷贝逐字节拷贝的特点我们可以看出来 这两个array的地址是相同的 他们指向的是同一块空间
这就会导致在析构的时候 先释放了st2 再释放st1的时候就访问了野指针 程序直接崩溃

下面这段代码是深拷贝的写法

// Stack st2(st1);
//s就是st1 this是st2
Stack(const Stack& s)
{
	DataType* tmp = (DataType*)malloc(s._capacity *(sizeof(DataType)));
	if (tmp == nullptr)
	{
		perror("malloc fail");
		exit(-1);
	}
	//上面几行看不懂的话不用管
	memcpy(tmp, s._array, sizeof(DataType) * s._size);

	_array = tmp;
	_size = s._size;
	_capacity = s._capacity;
}

在这里插入图片描述

而深拷贝则会根据array的大小 来开辟一块和array大小一样的空间 那么在析构的时候就没问题了

结论

所以在函数传参的时候 建议用引用 其次可以用指针 最不建议用传值
并且引用应该也是最方便的

结语

对于深浅拷贝的简单介绍到这里就结束了 后面会更深入的介绍 希望对你有帮助~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/372443.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

周报(20240204)

日期:2024.1.29 - 2024.2.4 本周工作: 1. 阅读论文 本周主要对这篇文献进行了阅读: 《用可学习的跳跃连接缩小U-Net中的语义差距:以医学图像分割为例》 背景 医学图像分割和随后对目标对象的定量评估为疾病诊断和治疗规划提…

在Vue中如何动态绑定class和style属性

在Vue中,动态绑定class和style属性是我们经常遇到的需求。这个功能允许我们根据不同的条件来动态改变元素的样式,让我们的应用更加灵活和富有交互性。在本篇博客文章中,我将带你深入探索在Vue中如何实现这一功能。 首先,让我们了…

c++中使用ifstream对文件按照行间隔或者符号间隔来读取

简单的文本存取与读取在的程序中是比较常见的,一般为了读取的时候便于区分数据,我们常常会用空格或者空行来隔开数据字段,所以对于读取文件的操作我们肯定会有些具体的需求比如按照行读取或者按照词来读取(或者说是以空格来间隔数…

函数调用栈是什么

今天在力扣leetbook上看《图解算法数据结构》中的空间复杂度这一小节,看到如下这句话: “程序调用函数是基于栈实现的,函数在调用期间,占用常量大小的栈帧空间,直至返回后释放。” 这句话的意思是,在程序中…

SQL必知必会笔记(13~16章)

第十三章 创建高级联结 1、别名:缩短SQL语句,允许在一条Select语句中多次使用相同的表 SELECT A.Name, A.Maths, A.English FROM transcript AS A INNER JOIN student_id As B ON A.Name B.Name; 2、Oracle数据库中没有AS关键字,直接在表名或…

【计算机学院寒假社会实践】——服务走进社区,共绘幸福蓝图

为深入贯彻落实志愿者服务精神,扎实推进志愿者服务质量,2024年1月28日,曲阜师范大学计算机学院“青年扎根基层,服务走进社区”社会实践队队员周兴睿在孙宇老师的指导下,来到山东省滨州市陈集街道社区开展了为期一天的“…

Unity_ShaderGraph节点问题

Unity_ShaderGraph节点问题 Unity版本:Unity2023.1.19 为什么在Unity2023.1.19的Shader Graph中找不见PBR Master节点? 以下这个PBR Maste从何而来?

MQ,RabbitMQ,SpringAMQP的原理与实操

MQ 同步通信 异步通信 事件驱动优势: 服务解耦 性能提升,吞吐量提高 服务没有强依赖,不担心级联失败问题 流量消峰 ​ 小结: 大多情况对时效性要求较高,所有大多数时间用同步。而如果不需要对方的结果,且吞吐…

Zookeeper相关面试准备问题

Zookeeper介绍 Zookeeper从设计模式角度来理解,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生了变化,Zookeeper就负责通知已经在Zoo…

SpringAOP+SpringBoot事务管理

项目搭建SpringAOPSpringBoot中管理事务AOP案例实战-日志记录日志系统 一、项目搭建 第一步:构建项目 第二步:导入依赖 第三步:配置信息 自动配置(项目自动生成的启动类) /*** 启动类:申明当前类是一个…

模拟被观察物体的位置和方向

开发环境: Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example demo解决问题:模拟被观察物体的位置和方向,以帮助用户理解相机在观察特定对象时的位置和朝向。vtkCameraOrientationWidget 模拟的是被观察…

Redis核心技术与实战【学习笔记】 - 17.Redis 缓存异常:缓存雪崩、击穿、穿透

概述 Redis 的缓存异常问题,除了数据不一致问题外,还会面临其他三个问题,分别是缓存雪崩、缓存击穿、缓存穿透。这三个问题,一旦发生,会导致大量的请求积压到数据库。若并发量很大,就会导致数据库宕机或故…

九州金榜|如何做好家庭教育

孩子的家庭教育是每个家庭都要做的,也是每个家长面临的事情,同样不同的家庭教育教育出来的孩子性格也各不相同,有时候家长看别别人家的孩子品学兼优非常羡慕,很多家长会把问题归结到孩子身上,其实有没有想过是家庭教育…

C++之函数重载,默认参数,bool类型,inline函数,异常安全

函数重载 在实际开发中,有时候需要实现几个功能类似的函数,只是细节有所不同。如交换两个变量的值,但这两种变量可以有多种类型,short, int, float等。在C语言中,必须要设计出不同名的函数,其原型类似于&am…

【新书推荐】6.2节 段寄存器

在16位汇编语言的源程序中,我们将源程序按照不同的功能和作用划分为若干个逻辑段,如数据段用来存储数据,代码段用来存储代码,堆栈段用来保存临时数据,附加段用来拷贝数据。我们可以把汇编语言的源程序抽象地理解为数据…

TCP与UDP:传输层协议的差异与选择

在计算机网络中,传输控制协议(TCP)和用户数据报协议(UDP)是两种常用的传输层协议。然而,随着互联网的快速发展,传统的TCP和UDP在某些场景下存在一些限制。为了解决这些问题,出现了新…

如何使用VS Code编写小游戏并实现公网游玩本地游戏【内网穿透】

文章目录 前言1. 编写MENJA小游戏2. 安装cpolar内网穿透3. 配置MENJA小游戏公网访问地址4. 实现公网访问MENJA小游戏5. 固定MENJA小游戏公网地址 前言 本篇教程,我们将通过VS Code实现远程开发MENJA小游戏,并通过cpolar内网穿透发布到公网,分…

No matching client found for package name ‘com.unity3d.player‘

2024年2月5日更新 必须使用Unity方式接入Unity项目!一句话解决所有问题。(真的别玩Android方式) 大致这问题出现原因是我在Unity采用了Android方式接入Firebase,而Android接入实际上和Unity接入方式有配置上的不一样,我…

爬虫工作量由小到大的思维转变---<第四十五章 Scrapyd 关于gerapy遇到问题>

前言: 本章主要是解决一些gerapy遇到的问题,会持续更新这篇! 正文: 问题1: 1400 - build.py - gerapy.server.core.build - 78 - build - error occurred (1, [E:\\项目文件名\\venv\\Scripts\\python.exe, setup.py, clean, -a, bdist_uberegg, -d, C:\\Users\\Administrat…

链表经典算法(+OJ刷题)

文章目录 前言一、移除链表元素二、链表的中间节点三.反转链表四.合并两个有序链表五.分割链表六.环形链表的约瑟夫问题总结 创作不易,点赞收藏一下呗!!! 前言 在上一节,我们介绍了单链表的增,删&#xff…