C++从入门到起飞之——深浅拷贝string类补充 全方位剖析!

news2024/11/23 19:14:52

🌈个人主页:秋风起,再归来~
🔥系列专栏:C++从入门到起飞          
🔖克心守己,律己则安

目录

1、浅拷贝

2、深拷贝

3、现代版写法的拷贝构造和赋值重载

4、再探swap!

5、写实拷贝(了解)

6、完结散花


1、浅拷贝

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

>就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一 不想分享就你争我夺,玩具损坏。

当对象当中有对资源的管理和申请时,浅拷贝有俩个问题:

        >1、当一个对象对资源改变时,另一个对象中的资源随之而变。

        >2、当对象进行销毁时会发生资源的多次释放。

>可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享。父 母给每个孩子都买一份玩具,各自玩各自的就不会有问题了。

2、深拷贝

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

3、现代版写法的拷贝构造和赋值重载

>拷贝构造(深拷贝)传统写法

	//拷贝构造(深拷贝)传统写法
	string(const string& s)
	{
		_str = new char[s._capacity + 1];
		strcpy(_str, s._str);
		_size = s._size;
		_capacity = s._capacity;
	}

 >拷贝构造(深拷贝)现代写法

void swap(string& s)
{
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}
//拷贝构造(深拷贝)现代写法
string(const string& s)
{
	string tmp(s._str);
	swap(tmp);
	//==this.swap(tmp);
}

注意:我们在string类内部自己实现一个swap交换函数,在实现自己的交换函数时,一定要在类内部指定命名空间std不然会调用this.swap,从而发生报错! 

深拷贝现代写法和传统写法的不同之处就在于,我们不自己手动去开空间给我们需要构造的对象,而是临时构造一个对象tmp,把开空间的任务交给了带参构造函数。然后,拷贝构造就窃取tmp的成果,用swap将this和tmp交换!从而达到拷贝构造的目的!

这里还需要注意的是我们一定要给this的_str初始化为nullptr,不然_str里面为空,还是随机值这是标准未规定的。如果,this的_str为随机值,那么在交换后,tmp在析构时会释放随机的空间。所以,我们可以在交换前置空,也可以直接在申明处给缺省值!

char* _str=nullptr;//指向字符串的指针
size_t _size=0;//有效字符个数(不包含'\0')
size_t _capacity=0;//空间大小(不包含'\0')

>赋值重载传统写法

	//显示赋值运算符重载
	string& operator=(const string& s)
	{
		if (this != &s)
		{
			delete[] _str;
			_str = new char[s._capacity + 1];
			strcpy(_str, s._str);
			_size = s._size;
			_capacity = s._capacity;
		}
		return *this;
	}

>赋值重载现代写法1

	string& operator=(const string& s)
	{
		if (this != &s)
		{
			string tmp(s.c_str());
			swap(tmp);
		}
		return *this;
	}

与拷贝构造的写法类似,不过赋值重载中tmp做的事更多。它不仅帮this拷贝构造数据,在交换数据后还要帮忙把this原来指向的资源释放(就好比我做饭给你吃,我还要顺便在你吃完后把碗筷洗了)。

>赋值重载现代写法2

string& operator=(string tmp)
{
	swap(tmp);
	return *this;
}

这种写法就更加简单了,我们直接在传值传参的时候构造tmp,再进行交换!但是,这种写法在自己给自己赋值时避免不了无用的拷贝构造与交换。不过,这种情况很少并且上面的写法并没有问题,无伤大雅!

4、再探swap!

>std::swap

我们可以看到,std中的swap其实就是一个函数模版,如果我们在string类里面用std中的swap函数的话,一个交换函数就会有三次拷贝构造,效率太低了。所以我们在string中有属于自己的swap函数,这也告诉我们,对内置类型我们可以用std::swap,但是对于类类型,我们不建议使用!

>string的成员函数swap

string成员函数的swap就是直接改变指针的指向,避免了拷贝构造。但是,既然成员函数中已经有了swap函数,那么为什么还要在string中定义非成员函数swap呢?

>string的非成员函数swap

 注意看这段英文,这里说这是泛型算法交换的重载,它通过相互转移对其内部数据的所有权到另一个对象(即,字符串交换对其数据的引用,而不实际复制字符)来提高其性能:它的行为就像调用了 x.swap(y)。

这一点我们从反汇编也可以看出来,实际上,它最终还是调用了string的成员函数swap!

这就是在string中还要再实现一个非成员函数swap的意义,有些人并不知道调用string类成员函数swap和在std::定义的swap函数模版有什么不同,所以就可能会直接用全局的函数模版swap。但是,为了让效率提高,在std中就直接再次实现了一个函数swap!既然已经有现成的并且匹配的swap函数,我们在直接调用swap时并不会通过模版再次生成swap函数,而是直接调用现成的(编译器也会偷懒哦~)!

所以,我们以后在交换string类型的对象时,使用哪一个swap都可以! 

5、写实拷贝(了解)

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

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

>因为随着C++11的更新,移动构造的出现,写实拷贝已经慢慢失去其优势不太常用了,所以这里就不进行详细的讲解。(如果友友们实在感兴趣,可以点击下面的链接看看哦~)

写实拷贝扩展icon-default.png?t=N7T8https://coolshell.cn/articles/12199.html写时拷贝在读取时的缺陷icon-default.png?t=N7T8https://coolshell.cn/articles/1443.html

6、完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

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

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

相关文章

[开端]如何看待“低代码”开发平台的兴起

如何看待“低代码”开发平台的兴起? 近年来,“低代码”开发平台如雨后春笋般涌现,承诺让非专业人士也能快速构建应用程序。这种新兴技术正在挑战传统软件开发模式,引发了IT行业的广泛讨论。低代码平台是提高效率的利器&#xff0…

从零开始构建基于ChatGPT的嵌入式(Embedding)本地医疗客服问答机器人模型(看完就会,看到最后有惊喜)

1、前言 代码全部开源,GitHub地址为: github.com/aehyok/go-o… 前端完全也能搭建, 前端完全也能搭建, 前端完全也能搭建, 本文中我使用的是后端语言golang,来调用的所有外部接口,但它们均是restful api,所以如果你使用的是其他…

FPGA开发——IP核的FIFO调用

一、简介 FIFO 的英文全称是 First In First Out,即先进先出。 FPGA 使用的 FIFO 一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即所谓的跨时钟域信号传递。它与 FPGA 内部的 RAM 和 ROM…

C语言 | Leetcode C语言题解之第330题按要求补齐数组

题目&#xff1a; 题解&#xff1a; int minPatches(int* nums, int numsSize, int n) {int patches 0;long long x 1;int index 0;while (x < n) {if (index < numsSize && nums[index] < x) {x nums[index];index;} else {x << 1;patches;}}retu…

网通设备有关工程师产品设计时如何选择适合的集成网口座呢?

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;今天分享的是网通设备有关工程师产品设计时如何选择集成网口座呢&#xff1f; 下面我们一起来看看网通设备有关工程师产品设计时是选择集成网口座的 综合多年与网通产品或相关…

微调LLama 3.1——七月论文审稿GPT第5.5版:拿早期paper-review数据集微调LLama 3.1

前言 对于llama3&#xff0c;我们之前已经做了针对llama3 早7数据微调后的测评 去pk llama2的早7数据微调后&#xff0c;推理测试集中的早期paper&#xff1a;出来7方面review去pk gpt4推理测试集中的早期paper&#xff1a;7方面reviewground truth是早期paper的7方面人工rev…

13.3 正则表达式的应用

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 工&#x1f497;重&#x1f497;hao&#x1f497;&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

vue 打包时候的分包

export default defineConfig({plugins: [vue()],resolve: {alias: {: fileURLToPath(new URL(./src/, import.meta.url))}},// 分包&#xff0c;node_modules中的单独打包成名字为vendor的js文件build: {rollupOptions: {manualChunks(id) {if (id.includes(node_modules)) {r…

汽车测试,引领国际

汽车测试及质量监控博览会&#xff08;中国&#xff09;(Testing Expo China 2024 - Automotive )是引领世界的领先国际展会&#xff0c;将于 2024 年 8 月 28-30日在上海世博展览馆举行。展示汽车测试、开发和验证技术的各个方面&#xff0c;每年在中国、欧洲和美国举办&#…

Openssh升级到>=9.6版本导致sftp不兼容的解决办法

因为要修复漏洞&#xff0c;所以得升级openssh&#xff0c;但从9.6开始&#xff0c;默认编译出来的openssh&#xff0c;无法兼容之前的sftp客户端了&#xff0c;大概的错误信息就是算法协商不一致。 解决办法其实也简单&#xff0c;就2步&#xff1a; 1. 编译的时候&#xff0c…

Linux学习记录(五)-------三类读写函数

文章目录 三种读写函数1.行缓存2.无缓存3.全缓存4.fgets和fputs5.gets和puts 三种读写函数 1.行缓存 遇到新行&#xff08;\n&#xff09;,或者写满缓存时&#xff0c;即调用系统函数 读&#xff1a;fgets,gets,printf,fprintf,sprintf写&#xff1a;fputs,puts,scanf 2.无缓…

Flink Checkpoint expired before completing解决方法

在Flink消费Kafka日志的时候出现了这样的一则报错&#xff0c; JobManager报错如下&#xff1a; 2024-03-07 15:21:12,500 [Checkpoint Timer] WARN org.apache.flink.runtime.checkpoint.CheckpointFailureManager [] - Failed to trigger or complete checkpoint 181 for …

面试官:怎样设计一个分布式任务调度平台?

大家好&#xff0c;我是君哥。 在工作中&#xff0c;批量任务调度的需求经常会遇到&#xff0c;比如下面的几个场景&#xff1a; 数据迁移&#xff1a;从数据库 A 批量读取数据&#xff0c;加工后把数据写入数据库 B&#xff1b; 消息通知&#xff1a;运营商批量给客户发送短…

宠物空气净化器什么牌子好?希喂、美的测评推荐

家里养了两只猫&#xff0c;每天晚上和我入眠&#xff0c;早上睡醒过来就看到猫睡在我身边&#xff0c;这一刻幸福感爆棚。幸福感爆棚的同时&#xff0c;无力感也袭来。主要是因为虽然每天玩得都很开心&#xff0c;但是家里的变化让我不禁感慨这是真实存在的吗。一回到家就会发…

【Material-UI】Checkbox组件:受控模式详解

文章目录 一、什么是受控组件&#xff1f;二、受控模式的基本用法1. 核心概念2. 代码分析 三、受控组件的优势与应用场景1. 确保数据的一致性2. 简化复杂的表单逻辑3. 轻松实现状态回显 四、受控模式的最佳实践1. 状态管理2. 优化性能3. 处理异步数据 五、结论 在Web开发中&…

【数据结构-前缀哈希】力扣3026. 最大好子数组和

给你一个长度为 n 的数组 nums 和一个 正 整数 k 。 如果 nums 的一个 子数组 中&#xff0c;第一个元素和最后一个元素 差的绝对值恰好 为 k &#xff0c;我们称这个子数组为 好 的。换句话说&#xff0c;如果子数组 nums[i…j] 满足 |nums[i] - nums[j]| k &#xff0c;那么…

如何通过AquilaInsight快速查看每天有哪些异常/慢查询?

友情链接&#xff1a; AquilaInsight核心功能及角色概览Aquila的核心功能介绍DBA Service的核心功能介绍刚部署好Aquila Insight&#xff0c;第一次如何使用如何通过Aquila Insight快速定位一个查询为什么慢&#xff1f;Aquila 添加自定义监控信息和告警的示例当Quark/Incepto…

[器械财讯]威高血液净化:中国血液透析市场的领军企业冲刺IPO

一、IPO冲刺&#xff1a;威高血净迎来新进展 山东威高血液净化制品股份有限公司&#xff08;以下简称“威高血净”&#xff09;在2023年12月30日正式启动IPO后&#xff0c;于2024年8月2日迎来新进展&#xff0c;其审核状态在上海证券交易所更新为“已问询”。尽管2024年医药行…

没有获取淘宝API的资质怎么获取淘宝数据

淘宝是头部电商平台之一&#xff0c;每个自研商家或电商软件服务商想要开发电商管理功能模板就少不了要对接淘宝API。淘宝API是在淘宝开放平台提供的&#xff0c;自研商家和软件服务商接入淘宝开放平台需要经过一系列审核和申请流程&#xff0c;要求资质和相关资料符合对应的要…

Windows下,C# 通过FastDDS高效通信

目录 1、安装FastDDS 库2、使用IDL定义自己的数据格式3、生成DLL3.1 托管 &#xff08;Managed&#xff09;模式3.2 非托管 &#xff08;Unmanaged&#xff09;模式 -- 可用于Unity 代码示例 eprosima Fast DDS is a C implementation of the DDS (Data Distribution Service) …