【C++】string类的深浅拷贝问题

news2024/9/20 20:27:40

string类的深浅拷贝问题

  • 浅拷贝问题
  • 构造/析构函数
  • 拷贝构造/赋值运算符重载的多种写法

浅拷贝问题

我们知道,定义一个类的时候,如果我们没有写构造,拷贝构造,赋值运算符重载,析构方法的话,编译器会自动生成。当该类成员中涉及到资源的管理时,实现的就是浅拷贝。所以,以上这几种方式是必须要程序猿手动实现的。

举例来看:
在这里插入图片描述
图中所示:实现了构造和析构,没有显式定义拷贝构造,这时先创建了一个s1,当使用拷贝构造创建s2时,由于没有显式定义,编译器自动生成的实际上是直接将s1中str的值直接复制给了s2中的str,那这样就导致两个指针指向了同一块内存空间。当test函数退出时,先释放s2,调用析构函数,可以成功将s2中str指向的内存空间释放掉,接着释放s1,这时调用析构函数进行释放时,s1中的str已经是野指针了,释放野指针就会报错

因此当前代码奔溃的根本原因就是浅拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。

要想实现深拷贝,我们要从逻辑上知道如何做
在这里插入图片描述

每通过拷贝构造创建一个新的string对象的时候,都需要给新创建的对象开辟空间,将原对象中指向空间的内容拷贝到新空间,让原对象和新对象都拥有各自的空间,这样就可以实现深拷贝。

构造/析构函数

注意:在构造时需要进行资源管理,析构时需要进行资源释放

class String
{
public:
	String(const char* str = "")
	{
		if (str == nullptr)
			str = "";
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
private:
	char* _str;
};

拷贝构造/赋值运算符重载的多种写法

注意:进行拷贝构造/赋值运算符重载时,有多种写法,主要分为传统版和现代版,为了实现深拷贝,实际上要让新创建的string对象拥有各自的空间。

//传统版:代码易懂,但是代码重复率高
	String(const String& s)
		:_str(new char[strlen(s._str)+1])// 给当前对象的指针变量new一段空间,+1是为了存放'\0'
	{
	    // 将s中指向空间的内容拷贝到当前对象,当前对象就拥有了和s相同内容的空间,但是两份空间是独立的
		strcpy(_str, s._str);
	}
	String& operator=(const String& s)
	{
		//需要判断是否为自己给自己赋值
		if (this != &s)
		{
			//先创建一个临时指针,空间大小和s中指针指向的空间一致
			char* tmp = new char[strlen(s._str) + 1];
			//将其内容拷贝至tmp中
			strcpy(tmp, s._str);
			//释放旧空间
			delete[] _str;
			//将指针指向修改为新指向
			_str = tmp;
		}
		return *this;
	}

现代版的写法,省去了重复的new和strcpy,而是直接使用swap,交换两个指针的指向即可,临时对象在函数结束时调用析构函数释放资源,将临时对象原来指向的空间返回给需要空间的对象。

//现代版:代码简洁,但是不易理解
	String(const String& s)
		:_str(nullptr)//后续需要将tmp中指针指向改为nullptr,调用析构函数释放时就不做任何操作了
	{
		//用构造函数构造一个临时对象
		String tmp(s._str);
		//将当前对象中的指针指向和临时对象中指针指向交换,当前对象就拥有和s中指针指向相同内容的空间,
		//同时,tmp中指针的指向是nullptr,调用析构函数释放时也不需要做任何操作
		swap(_str, tmp._str);
	}
	// 传址方式的赋值运算符重载
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			String tmp(s._str);
			//调用析构函数时,_str释放的是原来tmp的空间,tmp释放的是原来_str的旧空间
			swap(_str, tmp._str);
		}
		return *this;
	}
	// 传值方式的赋值运算符重载
	String& operator=(String s)
	{
		//以传值方式传递时,s是原来s的临时拷贝,可以直接通过交换的方式,
		//让_str获得临时s指针指向的内容,临时s释放的是原来_str的旧空间
		swap(_str, s._str);
		return *this;
	}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Django学习笔记001之创建项目

学习目标: 了解前端后台框架 掌握vs搭建Django环境 学习内容 1.背景学习 优缺点: 2.vs搭建Django开发环境 2.1. 准备vscode工具 可以从github上获取:https://github.com/microsoft/vscode。 2.2. 构建python虚拟环境 使用的命令是pyth…

微分方程数值解法(Runge-Kutta法PLC实现)

微分方程数值解法之欧拉法请参看下面的博客文章: 微分方程数值解法(PID仿真用一阶被控对象库PLC算法实现)_数学微积分算法plc编程实例_RXXW_Dor的博客-CSDN博客微分方程除极特殊情况外,大部分不可能求出它的精确解,只能用各种近似方法得到满足一定精度的近似解,微分方程由…

CTA进网检验要求修订原则和变更说明 SAR新国标在2024年正式实施

《进网检验要求文件》 实行定期及动态更新原则,其中检测项目应能体现进网监管的职责定位。 第一部分 基本功能性能 第二部分 空间性能 SAR 新版进网检验要求细化了各场景的测试距离: SAR新要求的实施日期: 第二部分 空间性能 EMC 第二部分 空…

【MySQL】查询中,NULL值转换为空字符串

系列文章 C#底层库–MySQLBuilder脚本构建类(select、insert、update、in、带条件的SQL自动生成) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库操作辅助类(推荐阅读&#xff0…

【browserify】一步步教你学会browserify

https://www.cnblogs.com/fsg6/p/13139627.html Browserify browserify的官网是http://browserify.org/,他的用途是将前端用到的众多资源(css,img,js,…) 打包成一个js文件的技术。 比如在html中引用外部资源的时候,原来我们可能这样写 &l…

C嘎嘎~~ [类 上篇]

类 上篇 1.面向过程和面向对象的认识2.类的引入3.类的定义4.类的访问限定符和封装4.1封装4.2访问限定符 5.类的作用域 1.面向过程和面向对象的认识 面向过程 和 面向对象的区别: 面向过程关注的是过程, 而面向对象关注的是对象之间的关系, 交互. C语言是面向过程的, 而C是面向对…

webshell gif图片文件绕过

目录页/dev/index. php允许GIF上传。尝试上传不同的文件类型将被拒绝。 这可以通过首先上传合法的GIF文件来绕过。使用了一个小的GIF https://giphy.com/gifs/obi-won-hvE0PhVAnGQAo 下载一个小的字节图片测试 上传文件并使用Burpsuite捕获请求。尝试上传时的请求应类似于下…

淘宝天猫店铺新品如何运营?

新品在店铺运营过程中是十分重要的部分,你知道新品在店铺运营中有何作用?了解新品运营机制吗?今天就来快速了解关于新品的知识点。 新品在店铺运营的角色: 01、商品生命周期有限 商品的普遍生命周期在3个月左右,3个…

Codeforces Round 867 (Div. 3)

Problem - E - Codeforces 思路: 首先,如果n为奇数,中间那个数无法调整,所以只考虑偶数只有26个字母,我们用cnt[]记录每个字母需要交换的对数。设maxn为交换对数最多的字母。显然,如果cnt[maxn]>n/2,显…

速锐得解码奔驰CAN数据应用于海外车联网远程控制与防盗系统

人们常说,奔驰征服一切,你征服奔驰。速锐得帮你征服奔驰的数据。 前日,有个海外客户,问我们做了奔驰哪些数据,他们需要一个车联网的远程控制系统,用于管理他们的车队。客户比较豪横,大多数都是…

大数据管理中心规划设计方案(ppt可编辑)

本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除。 统一汇聚 推动业务数据协同5 价值提炼 支撑精准服务与科学管理6 实时感知 辅助城市治理高效运行7 大数据资源平台目标体系规划11 建设目标与思路12 使能高效协同&#xff0…

榜上有名 | 创宇盾荣登“2023 IT市场权威榜单”!

4月20日,已连续成功举办23届的IT市场年会在北京举行,作为权威咨询机构赛迪主办,中国IT业界延续时间最长的年度盛会之一,“2023 IT市场年会”隆重发布重磅权威榜单。 创宇盾作为云防护领域专业防护产品,在国家经济产业…

C++的默认成员函数

上一次我们说到了C的类,我们还知道在C的类中可以写函数,而且这个函数也属于这个类,我们可以直接使用这个类的对象去调用这个函数。 今天我们来看一下C的六个默认成员函数(这里说是6个,但是重要的只有4个) 构造函数 在C语言中&a…

Raft 共识算法3-日志复制

Raft 共识算法3-日志复制 Raft算法中译版地址:https://object.redisant.com/doc/raft%E4%B8%AD%E8%AF%91%E7%89%88-2023%E5%B9%B44%E6%9C%8823%E6%97%A5.pdf 英原论文地址:https://raft.github.io/raft.pdf Etcd Assistant 是一款 etcd 可视化管理软件&a…

idea使用 ( 一 ) 安装及初步使用

1.介绍 1.1.什么是 IDE 集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面]等工具。简单说就是开发工具,java开发中常用的…

一文读懂数据安全分级分类

目录 为什么要分级分类? 通用数据分级分类框架 数据分类 数据分类的常用方法 数据分类流程 数据分级 数据分级的常用方法 数据定级流程 行业数据安全分级分类指南 金融行业 电信行业 政务数据 健康医疗 企业实践 附录:数据分级分类大合集…

CAD格式交换全能:CAD DLL 15.0 Crack

添加对 SLDASM、FSAT、SAB、SMT、IPT 和 IFC 格式的支持。 2023 年 4 月 25 日 - 16:27 新版本 特征 改进的 3D: 打开 3D 文件时提高了速度。改进了对 SAT、STEP、SLDPRT、X_T、X_B、OBJ 格式的读取。添加了对 SLDASM、FSAT、SAB、SMT、IPT、IFC 格式的支持。添加了…

聊聊 maven的版本号version 以及maven指定版本号范围写法

1. 版本管理(version) 说了那么多废话,什么是版本管理?首先,一个健康的项目,通常有一个长期、合理的版本演变过程。版本管理是指项目整体版本的演变过程管理,就比如从1.0-SNAPSHOT --> 1.0 …

懂这3件事情,就能成功实施MES管理系统实现“数字化”工厂

当前,很多企业对MES管理系统需求旺盛,但是,要保证MES管理系统能够有效地实施,实现精益化管理,打造出一个“数字化”工厂,公司在实施MES管理系统之前,还必须弄明白为什么要MES管理系统、MES有什么…

QGIS数据可视化学习笔记04(完结)——POI检索和数据上图

一、POI数据检索概念 什么是POI检索?为什么要使用POI检索? 有的时候,我们可能不知道某个位置的地址,比如说北京朝阳图书馆,这个位置没有任何部门会去公布位置信息,但是我们又需要用到,这个时候就…