【C++】浅拷贝 / 深拷贝 / 写时拷贝

news2024/12/28 2:13:23

文章目录

  • 1. 经典的string类问题
  • 2. 浅拷贝
  • 3. 深拷贝
    • 3.1 传统写法的String类
    • 3.2 现代写法的String类
  • 4. 写时拷贝

1. 经典的string类问题

上一篇博客已经对string类进行了简单的介绍,大家只要能够正常使用即可。

链接:【C++】string

在面试中,面试官总喜欢让学生自己来模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。大家看下以下string类的实现是否有问题?

// 为了和标准库区分,此处使用String
class String
{
public:
	//String()
	//	:_str(new char[1])
	//{
	//	*_str = '\0';
	//}
	
	//String(const char* str = "\0")	// 错误示范
	//String(const char* str = nullptr)	// 错误示范
	String(const char* str = "")
	{
		// 构造String类对象时,如果传递nullptr指针,可以认为程序非法
		if (nullptr == str)
		{
			assert(false);
			return;
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
	
private:
	char* _str;
};

// 测试
void TestString()
{
	String s1("hello string");
	String s2(s1);
}

在这里插入图片描述

说明:上述String类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题时,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝。

2. 浅拷贝

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

就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一不想分享就你争我夺,玩具损坏。
在这里插入图片描述
可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享。父母给每个孩子都买一份玩具,各自玩各自的就不会有问题了。
在这里插入图片描述

3. 深拷贝

如果一个类中涉及到资源的管理,其拷贝构造函数,赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。
在这里插入图片描述

3.1 传统写法的String类

class String
{
public:
	String(const char* str = "")
	{
		// 构造String类对象时,如果传递nullptr指针,可以认为程序非法
		if (nullptr == str)
		{
			assert(false);
			return;
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	
	String(const String& s)
		: _str(new char[strlen(s._str) + 1])
	{
		strcpy(_str, s._str);
	}
	
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			char* pStr = new char[strlen(s._str) + 1];
			strcpy(pStr, s._str);
			delete[] _str;
			_str = pStr;
		}
		return *this;
	}
	
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
	
private:
	char* _str;
};

3.2 现代写法的String类

class String
{
public:
	String(const char* str = "")
	{
		if (nullptr == str)
		{
			assert(false);
			return;
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	
	String(const String& s)
		: _str(nullptr)
	{
		String strTmp(s._str);
		swap(_str, strTmp._str);
	}
	
	// 对比下和上面的赋值那个实现比较好?
	String& operator=(String s)
	{
		swap(_str, s._str);
		return *this;
	}
	
	//String& operator=(const String& s)
	//{
	//	if (this != &s)
	//	{
	//		String strTmp(s);
	//		swap(_str, strTmp._str);
	//	}
	//	return *this;
	//}

	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
	
private:
	char* _str;
};

传统写法就是老老实实自己开空间、自己拷贝数据、自己删除旧空间;而现代写法利用了swap()函数以及局部变量出作用域自动销毁的特性,让函数和编译器帮我们“打工”,我们只要坐享其成即可。这两种方式在效率上并没有什么区别,只是让代码看起来更简洁,但这又会使代码的可读性降低。总体来说,我还是更偏向于传统写法。

4. 写时拷贝

在这里插入图片描述

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。

引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,当某个对象被销毁时,先给该计数-1,然后再检查是否需要释放资源,如果计数为1,说明该对象是资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象也在使用该资源。


本文完

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

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

相关文章

PMP报考别跟风!搞懂这些问题不踩坑

大家好,今天我想和大家分享一下关于PMP报考的一些问题。近年来,PMP认证越来越受到大家的关注,但是报考PMP并不是一件简单的事情,需要我们认真考虑和准备。下面我将从PMP是什么、PMP有什么用、PMP适合什么人考、PMP是学什么的、PMP…

Git开发工具基本使用

文章目录 前言Git仓库基本概念基本环境安装清除原先配置生成秘钥配置Host添加公钥Github添加Gitee添加测试 本地仓库基本概览查看提交日志(log)版本回退添加文件至忽略列表分支分支冲突 远程仓库推送到远程仓库从远程仓库中抓取和拉取 在Idea中使用Git总结 前言 这里只是对Git…

WPF+Halcon 培训项目实战(10):HS组件绘制图案

文章目录 前言相关链接项目专栏运行环境匹配图片模板匹配加载模板文件运行结果 绘制十字标 WPF HS组件绘制图像绘制和生成的区别 前言 为了更好地去学习WPFHalcon,我决定去报个班学一下。原因无非是想换个工作。相关的教学视频来源于下方的Up主的提供的教程。这里只…

系列一、如何正确的获取Spring Cloud Alibaba Spring Cloud Spring Boot之间的版本对应关系

一、正确的获取Spring Cloud Alibaba & Spring Cloud & Spring Boot之间的版本对应关系 1.1、概述 Java发展日新月异,Spring Cloud Alibaba 、 Spring Cloud 、 Spring Boot在GitHub上的迭代也是异常的频繁,这也说明其社区很活跃,通…

NFS(文件存储服务)

题目 创建NFS共享文件夹,允许InsideCli可以远程挂载,映射挂载到D卷。共享文件夹路径为D:\shares\NFSshare。共享名称为NFSshare。允许未映射的用户访问。共享权限为读/写。服务配置步骤( 服务端 ) 步骤一 - 安装服务 步骤二 - 配置NFS服务 配置共享文件夹 选择共享路径

【BIG_FG_CSDN】C++ 数组与指针 (个人向——学习笔记)

一维数组 在内存占用连续存储单元的相同类型数据序列的存储。 数组是静态存储器的块;在编译时确定大小后才能使用; 其声明格式如下: 元素类型 数组名[常量];元素类型:数组中元素的数据类型; 常量&#…

Linux系统驱动要如何学习

1.你将获得: 快速上手 Linux 操作系统; 掌握Linux 内核工作原理; 掌握Linux 内核调试手段; 掌握复杂驱动:USB、PCIE、V4L2等 这门课程旨在为你打开Linux内核驱动的大门,让你在探索Linux内核的旅程中获得前…

HPM6750开发笔记《GPIO例程深度解析》

目录 创建工程: 代码分析: 1.头文件包含: 2.宏定义: 3.中断服务程序(ISR): 清除中断标志: 处理 LED 状态切换: 处理用户按键状态: 处理其他情况&…

Tomcat服务为什么起不来?

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 服务跑在Tomcat下面,有时候会遇到Tomcat起不来的情况。目前为止常遇到的情况有如下几种: 1. Tomcat服务…

Python模拟技巧实现自动抽屉登录和自动点赞

目录 一、引言 二、准备工作 三、自动抽屉登录 四、自动点赞 五、注意事项 六、案例分析 七、总结 一、引言 随着互联网的普及,人们越来越依赖于各种在线平台进行社交互动和信息获取。在这些平台上,用户需要登录才能享受各种服务,同时…

李宏毅机器学习第二十三周周报 Flow-based model

文章目录 week 23 Flow-based model摘要Abstract一、李宏毅机器学习1.引言2.数学背景2.1Jacobian2.2Determinant2.3Change of Variable Theorem 3.Flow-based Model4.GLOW 二、文献阅读1. 题目2. abstract3. 网络架构3.1 change of variable formula3.2 Coupling layers3.3Prop…

java数据结构与算法刷题-----LeetCode509. 斐波那契数

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难,但它就是固定套路而已。其实动态规划只…

跨境电商独立站代采1688货源网站

什么是淘宝代购 淘宝代购是近年兴起的一种购物模式,是帮国外客户购买中国商品。主要是通过万邦 科技的外贸代购系统,把淘宝、天猫等电商平台的全站商品通过API 接入到你的网站 上,瞬间就可以架设一个有数亿产品的大型网上商城,而且…

外贸人应该顺应趋势做外贸

2024年,有人疑惑外贸将如何发展?我想紧跟趋势是不会出错的,多年前网络没有如今那么发达,客户到中国参展或者来访就能确认订单。如今到处都是各种推广平台,客户足不出户就能在线上订购产品,如果你还是想靠之…

出版实务 | 书刊整体设计

文章目录 书刊整体设计概念目的原则内容外部装帧设计内文版式设计 书刊的形态术语书刊外表的翻本形态书刊的开本书刊装订样式种类平装精装骑马订装散页装 书刊的结构部件图书封面勒口书名页目录页 期刊面封底封 书刊版式设计概述版心、周空、版口、翻口的概念版面类型——和合面…

STM32CubeMX教程11 RTC 实时时钟 - 入侵检测和时间戳

目录 1、准备材料 2、实验目标 3、实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.1、外设初始化调用流程 3.2.2、外设中断调用流程 3.2.3、添加其他必要代码 4、常用函数 5、烧录验…

英伟达「摊牌」,朋友变对手

对于曾经拿着英伟达的GPU进行自动驾驶系统开发的初创公司来说,可能未必会想到:某一天,这家全球GPU巨头,曾经的合作伙伴会成为自己的直接竞争对手。 上周,英伟达官方公众号发布招聘消息,公司正在扩大其自动驾…

实验4.4 动态路由OSPF协议的配置

实验4.4 动态路由OSPF协议的配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.配置交换机和路由器的接口的IP地址等参数。2.配置动态路由OSPF协议,实现全网互通。 六、任务验收七、任务小结八、知识链接1.OSPF协议概念2.…

网络安全-真实ip获取伪造与隐藏挖掘

目录 真实ip获取应用层网络层网络连接TOAproxy protocol ip伪造应用层网络层TOA攻击proxy protocol 隐藏代理 挖掘代理多地ping历史DNS解析记录国外主机解析域名网站RSS订阅网络空间搜索引擎 总结参考 本篇文章学习一下如何服务如何获取真实ip,隐藏自己的ip&#xf…

Http状态:net::ERR_INCOMPLETE_CHUNKED_ENCODING

一、问题描述: 今天前端的小伙伴遇到一个js文件加载报错:net::ERR_INCOMPLETE_CHUNKED_ENCODING,不论如何刷新页面始终只有该文件加载失败,Chrome开发者工具中响应内容显示此请求没有可用的响应数据。 二、原因调查 排除非前端发…