C++:基于浅拷贝/深拷贝对模拟string类的一些优化

文章目录

  • string类和日期类
  • 浅拷贝/深拷贝
  • 对于上述代码的深拷贝写法
  • 正常版本和优化版本
  • 写时拷贝

string类和日期类

前面我们已经实现了string类和日期类,这两个类有没有想过它们有什么不同?
其实答案很明显,不同的地方在于string类中涉及到内存空间开辟,而日期类只是简单的对年月日三个变量进行一些变换

那有没有内存空间开辟对实际实现代码有什么影响?看下面代码

// error
class my_string
{
public:my_string(){_size = 0;_capacity = 0;_str = new char[_capacity+1];}~my_string(){delete[] _str;}
private:size_t _size;size_t _capacity;char* _str;
};int main()
{my_string s1;my_string s2;s2 = s1;return 0;
}

上面代码是可以运行吗?答案是不可以,原因在于什么?

编译器默认生成了六个成员函数,这当中包含了赋值重载,而代码中的s2=s1在编译器看来,就是把s1对象中的三个成员赋值给s2,这个过程就是所谓的浅拷贝,s2中的数据成员和s1完全相同,因此出了函数作用域后,s2会被先析构,s1继续析构,而s2被析构后它们所指向的空间已经被释放了,s1还要继续释放,很明显这是不可以的,因此程序会报错

因此我们就得出了一个初步结论,当成员变量涉及到动态开辟内存空间的时候,如果使用的还是编译器默认的赋值重载函数,就会涉及到一个空间被析构两次导致错误,这就是浅拷贝的弊端

浅拷贝/深拷贝

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

那如何解决?就需要用到深拷贝的知识:

可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享

对于上述代码的深拷贝写法

class my_string
{
public:my_string(){_size = 0;_capacity = 0;_str = new char[_capacity+1];}~my_string(){delete[] _str;}my_string& operator=(const my_string& s){_size = s._size;_capacity = s._capacity;_str = new char[_capacity + 1];strcpy(_str, s._str);return *this;}
private:size_t _size;size_t _capacity;char* _str;
};int main()
{my_string s1;my_string s2;s2 = s1;return 0;
}

那我们采用深拷贝的写法,就解决了这个问题,在前文string模拟实现中采用的也确实是这个方法,那这个方法可不可以进行继续优化?这就是后文要讨论的知识:如何优化深拷贝

正常版本和优化版本

对于深拷贝,上述的写法是一个正常的版本,而事实上这个版本是可以被优化的,例如可以这样优化:

	my_string(const my_string& s):_str(nullptr),_size(0),_capacity(0){my_string tmp(s._str);swap(tmp);}

上面就是一种对深拷贝的优化,我们可以借助一个tmp变量,构造出一个对象,再把这个对象和*this进行交换,这样也能实现深拷贝,这就是优化版本

写时拷贝

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

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

简单来说,写时拷贝就是在需要的时候再进行深拷贝,如果不进行写入就起到了提升效率的作用

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

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

相关文章

黑马点评学习笔记2

黑马点评学习笔记 1.缓存穿透1.1 缓存穿透是什么?1.2缓存穿透的解决方案1.2.1 缓存空对象1.2.2 布隆过滤1.2.3 其他解决方案 2.缓存雪崩2.1 缓存雪崩是什么?2.2 缓存雪崩的解决方案 3.缓存击穿3.1缓存击穿是什么?3.2缓存击穿的解决方案3.2.1互…

idea添加翻译插件并配置有道翻译

1、安装Translation插件 2、 创建有道云应用 有道智云控制台 3、设置idea 4、效果(选中文本右键翻译,默认快捷键CtrlShiftY)

篇二十二:解释器模式:处理语言语法

篇二十二:"解释器模式:处理语言语法" 开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。 另外有2本不错的关于设计模式的资料…

CentOS安装Postgresql

PG基本安装步骤 安装postgresql: sudo yum install postgresql-server初始化数据库:安装完毕后,需要初始化数据库并创建初始用户: sudo postgresql-setup initdb启动和停止服务: sudo systemctl start postgresql sudo…

一文详解高并发中的线程与线程池

一切要从CPU说起 你可能会有疑问,讲多线程为什么要从CPU说起呢?原因很简单,在这里没有那些时髦的概念,你可以更加清晰的看清问题的本质。CPU并不知道线程、进程之类的概念。CPU只知道两件事:1. 从内存中取出指令2. 执行指令&…

远景智能PMO负责人严晓婷受邀为第十二届中国PMO大会演讲嘉宾

上海远景科创智能科技有限公司PMO负责人严晓婷女士受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾,演讲议题:能源物联网产品标准项目和非标准项目的并行管理。大会将于8月12-13日在北京举办,敬请关注! 议题简要&#xff1…

React 入门学习

React 入门 一、基本认识1.1、前言1.2、什么是1.3、编译<br>1.4、特点1.5、高效 二、React环境和基本使用2.1、环境搭建2.2、脚手架项目基本使用2.2.1、src2.2.2、public2.2.3、package.json 三、JSX的理解和使用四、模块与模块化, 组件与组件化的理解4.1、模块与组件4.2…

nginx基础

nginx 具体就是一个轻量级以及高性能的web服务软件。 nginx特点 1、稳定性高。&#xff08;但不如apache&#xff09; 2、系统资源消耗比较低。&#xff08;处理http请求的并发能力较高&#xff0c;单台处理器可以处理3w-5w的并发请求&#xff09; 注&#xff1a;一般在企…

请解释一下JavaScript中的基本数据类型和引用数据类型,以及它们在内存中的存储方式。

1、请解释一下JavaScript中的基本数据类型和引用数据类型&#xff0c;以及它们在内存中的存储方式。 JavaScript中有两种类型的数据&#xff1a;基本数据类型&#xff08;也称为原始数据类型&#xff09;和引用数据类型。 基本数据类型包括&#xff1a; Number&#xff08;数…

用PointNet分类3D点云

在本教程中&#xff0c;我们将学习如何训练PointNet进行分类。 我们将主要关注数据和训练过程&#xff1b; 展示如何从头开始编码 Point Net 的教程位于此处。 本教程的代码位于这个Github库中&#xff0c;我们将使用的笔记本位于这个Github库中。 一些代码的灵感来自于这个Git…

Java仓库管理系统设计与实现

仓库管理系统 JAVA/数据库 课程设计 仓库管理系统 使用 MySQL和Idea 功能需求 1、问题描述 设计一个仓储管理系统&#xff0c;对仓库货品进行管理&#xff0c;出入库进行记录。 主要功能包括&#xff0c;货品添加修改&#xff0c;出库、入库、库存查询等功能&#xff0c;现…

【密码学】六、公钥密码

公钥密码 1、概述1.1设计要求1.2单向函数和单向陷门函数 2、RSA公钥密码体制2.1加解密2.2安全性分析 3、ElGamal公钥密码体制3.1加解密算法3.2安全性分析 4、椭圆曲线4.1椭圆曲线上的运算4.2ECC 5、SM2公钥密码体制5.1参数选取5.2密钥派生函数5.3加解密过程5.3.1初始化5.3.2加密…

安装linux操作系统

安装虚拟机的步骤&#xff1a; 安装linux系统 之后开启虚拟机 之后重启&#xff0c;打开虚拟机&#xff0c;登录root账号

探索泛型与数据结构:解锁高效编程之道

文章目录 引言第一部分&#xff1a;了解泛型1.1 为什么使用泛型1.2 使用泛型的好处 第二部分&#xff1a;泛型的使用场景2.1 类的泛型2.2 方法的泛型2.3 接口的泛型 第三部分&#xff1a;泛型通配符3.1 通配符3.2 通配符的受限泛型 第四部分&#xff1a;数据结构和泛型的应用4.…

微信小程序开发摇一摇功能_javascript技巧

方法定义&#xff1a; let shakeInfo {openFlag: false,// 是否开启摇一摇&#xff0c;*****注意&#xff1a;如果是小程序全局监听摇一摇&#xff0c;这里默认为trueshakeSpeed: 110,//设置阈值,越小越灵敏shakeStep: 2000,//摇一摇成功后间隔lastTime: 0,//此变量用来记录…

cmake 如何添加依赖库

1 说明 cmake 经常需要添加依赖库&#xff0c;但是不知如何确定依赖的库名称&#xff0c;如何编写 2 环境 ubuntu 机器 3 依赖方法 以 dbus 为例 3.1、确定库的名字 通过dpkg 命令搜索库名&#xff0c;如下所示&#xff0c;确定libdbus-1-dev 为自己需要的版本 usereba…

MySQL 事务

目录 一、事务的概念 二、事务的ACID特点 1&#xff09;事务的原子性 2&#xff09;事务的一致性 3&#xff09;事务的隔离性 &#xff08;1&#xff09;脏读 &#xff08;2&#xff09;不可重复读 &#xff08;3&#xff09;幻读 &#xff08;4&#xff09; 丢失更…

测试开发之前端篇-Web前端简介

自从九十年代初&#xff0c;人类创造出网页和浏览器后&#xff0c;Web取得了长足的发展&#xff0c;如今越来越多的企业级应用也选择使用Web技术来构建。 前面给大家介绍网络协议时讲到&#xff0c;您在阅读这篇文章时&#xff0c;浏览器是通过HTTP/HTTPS协议向服务器发送请求…

MyBatisPlus

一、MyBatis-Plus 1、简介 [MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 我们的愿景是成为 MyBatis 最好的搭档&#xff0c;就像魂斗罗中的 1P、2P&#…

探索ES高可用:滴滴自研跨数据中心复制技术详解

Elasticsearch 是一个基于Lucene构建的开源、分布式、RESTful接口的全文搜索引擎&#xff0c;其每个字段均可被索引&#xff0c;且能够横向扩展至数以百计的服务器存储以及处理TB级的数据&#xff0c;其可以在极短的时间内存储、搜索和分析大量的数据。 滴滴ES发展至今&#xf…