C++之深拷贝和浅拷贝

目录

浅拷贝

深拷贝

赋值运算符重载的深拷贝


在学习C++类和对象时我们学习了浅拷贝,本期我们将再次回顾浅拷贝并为大家讲述深拷贝的概念。

浅拷贝

在学习类和对象时我们学习了拷贝构造函数的概念,而且我们也知道,因为拷贝构造函数属于类的默认成员函数吗,所以当我们没有显示定义拷贝构造函数时,编译器会生成拷贝构造函数,编译器生成的拷贝构造函数对内置类型成员变量会完成字节序的值拷贝,对于自定义类型会去调用其拷贝构造函数。这里对内置类型成员变量进行的字节序值拷贝我们就称作浅拷贝,为什么我们我们要称字节序的值拷贝为浅拷贝呢?

我们通过依然自定义的string类中的拷贝构造函数为大家讲解:

代码如下:

class string{public:string(const char* str):_str(new char[strlen(str) + 1]){strcpy(_str, str);}~string(){delete [] _str;_str = nullptr;}private:char* _str;};void test1(){string s1("hello yjd");//调用拷贝构造函数string s2(s1);//调用赋值运算符重载string s3("hello world");s3 = s1;}

如上代码,我们自己定义了一个string类,string类由于我们没有声明拷贝构造函数,所以编译器会生成默认的拷贝构造函数,但是生成的默认的拷贝构造函数会对内置类型进行值拷贝,就会将s1对象的_str成员变量的值传给s2对象的_str成员变量。

所以就会导致下面这种情况,图示如下: 

运行截图如下:

不难发现,编译器提示我们出现了错误,这是因为编译器默认生成的拷贝构造函数对于内置类型是值拷贝,所以s1._str的值会赋给s2._str,就会导致两个指针变量指向了统一块动态申请的空间,既然是动态申请的空间在最后为了防止内存泄漏肯定是要使释放的,因为两个对象在小销毁之前都会调用析构函数进行资源的清理,所以这就会导致统一块空间被释放了两次,这边会导致错误,所以为了防止这种情况的出现,在此情境下诞生了深拷贝。 

深拷贝

什么是深拷贝,说白了深拷贝就是为了解决在堆上申请的空间被释放两次的问题,针对上述浅拷贝所产生的现象,为了防止两个指针指向了同一块空间,我们可以先让s2在堆上申请与s1大小相同的空间,在C语言中我们学习了字符串函数strcpy,我们可以通过这个函数实现两个字符串值的传递。

图示如下:

通过图示,不难发现,两个对象的成员变量指向了两个不同的空间,所以此时我们也就不用担心在堆区开辟的空间被释放两次的问题,所以深拷贝就解决了浅拷贝中所带来的不足。

代码如下:

	string(string& s):_str(new char[strlen(s._str)+1]){strcpy(_str, s._str);}

上述代码便是我们自己生成的拷贝构造函数代码,所以在今后学的的数据结构只要需要在堆上动态开辟空间,我们就需要自己定义拷贝构造函数。

赋值运算符重载的深拷贝

在学习类和对象时我们也学习了赋值运算符重载,赋值运算符重载和拷贝构造函数的区别是:

1.拷贝构造函数是用一个已经存在的对象初始化一个刚刚创建的对象。

2.赋值运算符重载是两个已经存在的对象之间进行赋值。

图示如下:

解析:因为赋值运算符重载也属于类的成员函数,当我们没有显示定义赋值运算符重载时,编译器也会默认生成一个赋值运算符重载,但是默认生成的赋值运算符重载和默认生成的拷贝构造函数是类似的,对于内置类型的成员变量,会完成字节序的值拷贝(浅拷贝),通过默认拷贝构造函数我们知道,浅拷贝是存在弊端的,所以对于在堆上开辟空间的数据结构,我们必须自己显示定义赋值运算符重载。

        其实整个过程和拷贝构造函数类似,不过赋值运算符重载我们要先释放掉原来的空间,释放掉原来的空间之后,在动态开辟一块与s1大小相同的空间,然后将这块空间的地址传给s3._str,然后通过strcpy函数实现字符串值的拷贝。

代码如下:

string& operator=(string& s){if (this != &s){char* tmp = new char[strlen(s._str) + 1];strcpy(tmp, s._str);delete[]_str;_str = tmp;}return *this;}

截图如下:

注意,代码中我们有两个需要注意的地方:

1.自己不需要给自己赋值,所以直接返回自身即可。

2.为了避免申请空间失败仍然释放掉原来空间的这种情况,我们定义了一个中间变量tmp,当空间申请失败时,我们则不释放原来的空间,当空间申请成功时,我们先赋值给临时字符串tmp,最后再将临时字符串赋值给成员变量_str就可以完成赋值运算符重载。

好了,深拷贝和浅拷贝的内容到这里就全部结束了,我们本次为大家带来的是传统版本的深拷贝,后期会为大家讲述效率更高的的深拷贝的方法。 

本期内容到此结束^_^

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用 树莓派 做成巨型的 Game Boy 你见过吗?

​几年前,华纳斯科奇(Warner Skoch)萌生了3D打印巨型Game Boy想法。他最初的计划是把它挂在墙上,用一个时钟作为屏幕,就像一件艺术品一样。后来,他的工匠头脑开始活跃起来,开始考虑通过添加 Ras…

3_js数组与函数的应用

1. 数组的应用 1.1 数组的概念 在计算机科学中,数组数据结构(英语:array data structure),简称数组(英语:Array),是由相同类型的元素(element)的…

MySQL undo日志精讲2-undo日志写入

通用链表结构 在写入undo日志的过程中会使用到多个链表,很多链表都有同样的节点结构,如图所示: 在某个表空间内,我们可以通过一个页的页号和在页内的偏移量来唯一定位一个节点的位置,这两个信息也就相当于指向这个节点…

基于Java+Swing实现大鱼吃小鱼小游戏(含用户登陆、注册功能)

基于JavaSwing实现大鱼吃小鱼小游戏 一、系统实现二、功能展示1.效果演示2.游戏界面3.游戏运行界面4.用户登陆 三、其他系统四源码下载 一、系统实现 1、创建窗口对象Ui 2、背景的绘制 3、键盘的监听事件 4、将己方鱼放上去 5、让小鱼移动 6、其他的鱼并引导(先创建…

用户管理第2节课--idea 2023.2 后端--实现基本数据库操作(操作user表) -- 自动生成

一、插件 Settings... 1.1 File -- Settings 1.2 Settings -- Plugins 1.2.1 搜索框,也可以直接搜索 1.3 Plugins -- 【输入 & 搜索】mybatis 1.3.1 插件不同功能介绍 1.3.2 翻译如下 1.4 选中 Update,更新下 1.4.1 更新中 1.4.2 Restart IDE 1…

基于SpringBoot的考研专业课程管理系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高校教师管理模块2.4 考研专业模块2.5 考研政策模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 考研高校表3.2.2 高校教师表3.2.3 考研专业表3.2.4 考研政策表 四、系统展示五、核…

GPTs | Actions应用案例

上篇文章说道,如何使用创建的GPTs通过API接口去获取外部的一些信息,然后把获取的外部信息返回给ChatGPT让它加工出来,回答你的问题,今天我们就来做一个通俗易懂的小案例,让大家来初步了解一下它的使用法! …

nodejs安装指导教程

1.nodejs下载 去官网下载对应的安装包即可 2.安装 下载的文件如果是exe文件直接安装,在弹出指导安装的界面有个addpath,可以将其勾选上,免得再去系统的环境变量中添加该属性。达成的效果就是,让npm命令到文件各个地方都可以被使…

MySQL基本操作 DDL DML DQL三大操作介绍

DDL 数据(结构)定义 创建表DML 数据操作 增删改DQL 查询语句 DDL 数据(结构)定义 创建表 创建 删除数据 注释 --空格内容 创建数据库 CREATE DATABASE [if not exists] 数据库名 [ CHARSET utf8]eg:CREATE DATABASE IF NOT EXISTS school CHARSET utf8如果对应school不存在,…

数字门牌管理系统:提升数据质量与服务品质的关键

一、引言 在当今社会,各行各业对数据质量的要求越来越高。为了满足客户需求并遵循国家行业标准,数字门牌管理系统应运而生。该系统以建立项目建设标准规范为核心,旨在提升数据质量与服务品质。 二、建立标准规范,确保数据质量 …

ansible-playbook的Temlates模块 tags模块 Roles模块

Temlates模块 jinja模板架构,通过模板可以实现向模板文件传参(python转义)把占位符参数传到配置文件中去,生产一个目标文本文件,传递变量到需要的配置文件当中 (web开发) nginx.conf.j2 早文件当中配置的是占位符(声明…

GBASE南大通用数据库在Windows和Linux中创建数据源

Windows 中数据源信息可能存在于两个地方:在 Windows 注册表中(对 Windows 系统), 或在一个 DSN 文件中(对任何系统)。 如果信息在 Windows 注册表中,它叫做“机器数据源”。它可能是一个“用 …