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

🌈个人主页:秋风起,再归来~
🔥系列专栏: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.rhkb.cn/news/395479.html

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

相关文章

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

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

同态加密和SEAL库的介绍(二)BFV 基础方案实现

写在前面: 本篇具体讲解如何使用 BFV 加密方案对加密的整数进行简单的计算(一个多项式评估),来源是官方提供的示例。BFV 是比较常见的方案,在很多大模型推理的时候,都是将浮点数的权重和输入变换成…

MongoDB学习笔记(三)

使用Python操作MongoDB: 使用管理员用户:

web基础与http协议与配置

目录 一、web基础 1.1 DNS与域名(详解看前面章节) 1.2 网页的概念(HTTP/HTTPS) 1.2.1 基本概念 1.2.2 HTML文档结构(了解) 1.2.3 web相关重点 1.2.4 静态资源和动态资源 二、http协议 2.1 概述 2.2 cookie和session&…

云原生真机实验

基于Proxmox VE构建中小企业云计算平台 首先Proxmox VE是什么?能用来做什么? Proxmox VE是一个完整的企业虚拟化开源平台。借助内置的 Web 界面,可以在单个解决方案上轻松管理 VM(开虚拟机的) 和容器、软件定义的存储和网络、高可用性群集以…

STM32开发之移植FreeRtos

一、新建STM32工程项目 (1)打开keil新建工程文件夹 (2)选择芯片型号 接下来会弹出来一个新建工程的小助手,我们关闭就好,接下来我们的工程就创建好了,但是工程还是空的 二、添加STM32的相关固件…

搭建 Web 群集Haproxy

案例概述 Haproxy 是目前比较流行的一种群集调度工具,同类群集调度工具有很多,如 LVS 和Nginx。相比较而言,LVS 性能最好,但是搭建相对复杂;Nginx 的upstream模块支持群集功能,但是对群集节点健康检查功能不强&#xf…

【C++】模版详解

1、概念 C模版分两类&#xff1a;函数模版和类模版 1&#xff09;函数模板的格式 template <class 形参名&#xff0c;class 形参名&#xff0c;......> 返回类型 函数名(参数列表) {函数体 }例如&#xff1a; template <class T> void swap(T& a, T& b…

机器人主板维修|ABB机械手主板元器件故障

【ABB机器人电路板故障原因诊断】 针对上述故障现象&#xff0c;我们需要对ABB机器人IO板进行详细的故障诊断。以下是一些可能的故障原因&#xff1a; 1. 元器件老化或损坏&#xff1a;ABB机械手安全面板上的元器件在长期使用过程中可能出现老化、损坏或接触不良等问题&#xf…

Unity 使用字符串更改Text指定文字颜色、大小、换行、透明

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、使用字符串改变文字属性的方法&#xff08;一&#xff09;修改颜色&#xff08;二&#xff09;修改大小&#xff08;三&#xff09;换行&#xff08;四&…

NC 矩阵的最小路径和

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 给定一个 n *…

【漏洞复现】某赛通数据泄露防护(DLP)系统 NetSecConfigAjax SQL注入漏洞

0x01 产品简介 某赛通新一代数据泄露防护系统&#xff08;简称 DLP&#xff09;&#xff0c;以服务企事业单位进行数据资产梳理、数据安全防护为目标。系统采用平台化管理&#xff0c;将终端DLP、网络DLP、邮件DLP、存储扫描DLP、API 接口DLP 进行统一管理&#xff0c;模块化控…

LVS详解

目录 一、LVS简介 LVS 官网: 二、LVS 负载均衡模式 2.1 LVS-NAT模式&#xff1a; 2.1.1 简介 2.1.2 工作流程图&#xff1a; 2.1.3 说明&#xff1a; 2.1.4 LVS-NAT的优缺点&#xff1a; 2.2 LVS-DR模式&#xff1a; 2.2.1 简介 2.2.2 工作原理&#xff1a; 2.2.3 工作…

Android----Depth Anything尝鲜 小米手机部署

题目要求&#xff1a;了解Depth Anything (以及Depth Anything v2)基本原理&#xff0c;创新点。 Depth Anything 论文&#xff1a;Depth Anything: Unleashing the Power of Large-Scale Unlabeled Data 参考代码&#xff1a;Depth-Anything-Android GitHub 分析&#xff1a; …

应急响应:D盾的简单使用.

什么是应急响应. 一个组织为了 应对 各种网络安全 意外事件 的发生 所做的准备 以及在 事件发生后 所采取的措施 。说白了就是别人攻击你了&#xff0c;你怎么把这个攻击还原&#xff0c;看看别人是怎么攻击的&#xff0c;然后你如何去处理&#xff0c;这就是应急响应。 D盾功…

【算法】最短路径算法思路小结

一、基础&#xff1a;二叉树的遍历->图的遍历 提到搜索算法&#xff0c;就不得不说两个最基础的思想&#xff1a; BFS&#xff08;Breadth First Search&#xff09;广度优先搜索 DFS&#xff08;Depth First Search&#xff09;深度优先搜索 刚开始是在二叉树遍历中接触这…

【vue+mathjax】mathjax的使用

方法一、引用外网的地址 第一步&#xff1a;在public/index.html中引入地址 <!DOCTYPE html> <html><head><meta charset"utf-8" /><meta http-equiv"X-UA-Compatible" content"IEedge,chrome1" /><metaname…

力扣刷题-环形链表判断是否有环

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 首先&#xff0c;我们先来看一下这段代码&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ bool …

延时队列与redis and rabbitmq

延时队列是什么 延时队列&#xff08;Delay Queue&#xff09;是一种特殊的消息队列&#xff0c;它允许你在添加消息时设置一个延时时间&#xff0c;消息只有在延时时间到达后才能被消费。这种机制在分布式系统中非常有用&#xff0c;常用于处理需要在指定时间后执行的任务&am…

力扣面试经典算法150题:多数元素

多数元素 今天的题目是力扣面试经典150题中的数组的简单题: 多数元素 题目链接&#xff1a;https://leetcode.cn/problems/majority-element/description/?envTypestudy-plan-v2&envIdtop-interview-150 题目描述 给定一个大小为 n 的数组 nums&#xff0c;其中包含 n 个…