C++STL初阶(3):string模拟实现的完善

news2024/11/25 18:47:21

1.流提取>>的优化(利用缓存区的思想)

istream& operator>>(istream& is,string& str) {
	str.clear();
	char c;
	c = is.get();
	while (c != '\0' && c != '\n') {
		str += c;
		c = is.get();
	}
	return is;
}

        在上文的对string的实践中,对于>>的重载(如上代码),当我们需要输入很多文字的时候,因为每次都会利用一次push_back(+=的实现是对push_back的复用),扩容相对较频繁。需要经历很多次扩容,开销较大。

解决办法1:通过reserve函数提前对str的空间进行规划 

           

        但是这样的reserve只对预计空间在100左右的string凑效。当要输入的字符很多时,依然需要多次扩容。

解决办法2:buff数组(利用缓冲区的思想):

先将输入的内容都放入buff数组中。

   加入并使用一个人为确定大小的buff数组,既避免了频繁扩容,也避免了一次性扩太多造成浪费。每次几乎都不会执行push_back,都是按照需要开的。

这是一种借助缓冲区的思路,每次都将即将输入的单个字符放在缓冲区。在有必要时,将缓冲区的内容一次性全部放进_str中以提升效率。

每当一次输入结束(输入了'\n'或者‘ ’) ,就从buff数组中全部拿出来并且通过append放入_str中,因此只会根据大小扩容一次。

必须有将buff数组的最后一个元素赋\0的操作,因为insert的逻辑是会覆盖掉原数组的\0的。

istream& operator>>(istream& is,string& str) {
	str.clear();
	char buff[128]; int i = 0;
	char c;
	c = is.get();
	while (c != '\0' && c != '\n') {
		buff[i++] = c;
		//0 - 126用来放char。由于insert的底层逻辑会覆盖\0,所以我们要在buff的末尾加\0
		if (i == 127) {
			buff[i] = '\0';
			str += buff;
			i = 0;
		}
		//str += c;
		c = is.get();
	}
	if (i != 0) {
		buff[i] = '\0';
		str += buff;
	}


2.拷贝构造与赋值运算符的现代写法

对于拷贝构造和赋值运算符重载,还有一种“现代写法”

先复习一下传统写法:

string::string(string& s) {
	_str = new char[s._size+1];//留一个位置给\0
	strcpy(_str, s._str);
	_size = s. _size;
	_capacity = s._capacity;
}

       传统思路基本都是根据传入的string引用开一个相应的空间,然后将_size和_capacity一个一个赋值。 

而现代写法的核心思路就是“让别人干活” :

       我们使用传入参数s的_str进行构造一个新的字符串tmp。接着将tmp的三项数据拷贝交换给this

                             

                             

当然,在string环境下的现代写法与传统写法没有特别大的优势,这是因为string的字符串的拷贝没有什么代价。 

还可以复用之前写的swap。

        比如上图,要将s1赋值拷贝给s2,也就是先通过构造tmp来获得一份s1的拷贝,然后将这份拷贝的内容交换。其本质是this不能显示调用构造函数。 

string::string(string& s) {
	string tmp(s._str);
	swap(tmp);
}

赋值运算符:

同样先观察原来的实现方法:

string& string::operator=(const string& s) {

	if (this != &s) {
    char* tmp = new char[s._size + 1];//留一个位置给\0
	strcpy(tmp,s._str);
	_size = s._size;
	_capacity = s._capacity;
	delete[] _str;
	_str = tmp;
	tmp = nullptr;
	}

	return *this;
}

依然先通过一个tmp来构造一个与s3一样一样的string,然后通过swap将tmp的内容与s1交换即可。 

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

swap的前面没有写作用域,在内部函数没有写前面的作用域就是对this进行该操作。

                       

由于tmp是临时变量,并且tmp指向了s1原来指向的"hello world\0",所以在出栈帧之后tmp会被销毁,而销毁又会调用析构函数。所以hello world所在的string就自动无了。

还可以优化成:

                

本质是利用传值传参的拷贝,不过这种方法记得改一改头文件中的参数类型。


3.写时拷贝(了解即可)

当我们对对象进行拷贝时不需要对对象进行修改时:

为了避免深拷贝对时间的浪费,我们能不能就利用浅拷贝呢?

目前已知的浅拷贝有两个如下问题:

                                                 

引用计数解决问题1:引入一个计数的整形变量,每次拷贝时都会将这个整形变量++,每析构一次一次将这个变量--  ; 每次最后一个析构的对象才释放空间,否则只是将对应的使用次数--

写时拷贝解决问题2:如果有需要改变原数组的需求时:还是按照原来的进行拷贝,但是只对“对原对象进行了写入和修改”的对象进行拷贝。因此,所有的写入函数,如:insert append erase push_back等都需要重新加一个函数:

copy_on_write:

而对于copy_on_write的内部:通过对引用计数的判断来决定是否需要深拷贝。

                      

因此,写时拷贝的目的是让不会改变原_str内容的对象共用一个_str,需要改变的还是会进行深拷贝。所以,只要不修改原_str,这样的拷贝方式稳赚不赔。

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

C++面试中string类的一种正确写法 | 酷 壳 - CoolShell 

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

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

相关文章

高考作文:时光之河,逐梦前行

时光之河,奔流不息,如同我们的人生旅途,充满了未知与挑战。站在2024年的高考门槛前,我们回望过去,展望未来,心中充满了期待与憧憬。 首先,让我们回顾一下这条时光之河中的点滴。过去的岁月里&am…

分享一个用python写的本地WIFI密码查看器

本章教程,主要分享一个本地wifi密码查看器,用python实现的,感兴趣的可以试一试。 具体代码 import subprocess # 导入 subprocess 模块,用于执行系统命令 import tkinter as tk # 导入 tkinter 模块,用于创建图形用…

vb开源项目推荐:PhotoDemon9.0一键批量去除图片水印

PhotoDemon 9.0作为一款开源免费的照片编辑器,提供了丰富的图片编辑和处理功能,可以通过PhotoDemon的批处理功能结合一些编辑技巧,来实现批量去除图片水印的目的。 以下是一个可能的步骤指南,用于在PhotoDemon 9.0中通过批处理间…

利用keepalived对zabbix-server做高可用,部署安装keepalived

有2台机器,每台都有1个zabbix-server,然后再每台上再装一个keepalived https://www.keepalived.org/download.html 1,创建安装路径 mkdir /usr/share/keepalived/2,在这个安装路径下面下载keepalived的软件包 我选的版本是1.3…

据报道,FTC 和 DOJ 对微软、OpenAI 和 Nvidia 展开反垄断调查

据《纽约时报》报道,联邦贸易委员会 (FTC) 和司法部 (DOJ) 同意分担调查微软、OpenAI 和 Nvidia 潜在反垄断违规行为的职责。 美国司法部将牵头对英伟达进行调查,而联邦贸易委员会将调查 OpenAI 与其最大投资者微软之间的交易。 喜好儿网 今年 1 月&a…

记录:linux桌面管理基础-X11协议(X window system)

1、认识X11 X11是X协议,版本号为11。X协议是专门被设计为linux桌面管理服务的,而linux桌面环境不像windows那样作为系统内核的一部分,作为一个普通程序运行在用户态上。该协议的设计初衷是为了linux的图形界面满足跨平台、跨网络、与具体硬件…

JVM面试基本问题整理

文章目录 1、说下对JVM内存模型的理解2、运行时常量池的位置3、常量池和运行时常量池的区别4、内存溢出和内存泄漏5、Java 对象大小计算6、GCROOT都有什么7、常用的JVM启动参数有哪些8、TLAB 1、说下对JVM内存模型的理解 1)线程私有区域 程序计数器(Pro…

ROS学习记录:栅格地图格式

一、机器人导航所使用的地图数据,就是ROS导航软件包里的map_server节点在话题 /map 中发布的消息数据,消息类型是nav_msgs消息包中的OccupancyGrid,它的中文意思的占据栅格,是一种正方形小格子组成的地图。 二、对障碍物进行俯视&…

单片机+TN901非接触式红外测温设计

摘要 温度测量技术应用十分广泛,而且在现代设备故障检测领域中也是一项非常重要的技术。但在某些应用领域中,要求测量温度用的传感器不能与被测物体相接触,这就需要一种非接触的测温方式来满足上述测温需求。本论文正是应上述实际需求而设计的…

搭建python虚拟环境,并在VSCode中使用

创建环境 python -m venv E:\python\flask\venv激活环境 运行下图所示的bat文件 退出环境 执行下面的语句 deactivateVSCode中配置: ①使用CTRLshiftp命令,使用CTRLshiftp命令,输入: Python: Select Interpreter②选择之前创建…

C++ 11 【线程库】【包装器】

💓博主CSDN主页:麻辣韭菜💓   ⏩专栏分类:C修炼之路⏪   🚚代码仓库:C高阶🚚   🌹关注我🫵带你学习更多C知识   🔝🔝 目录 前言 一、thread类的简单介绍 get_id…

IO进程线程(七)代码替换函数、守护进程

文章目录 一、代码替换函数(一)system函数(二)exec函数族 二、守护进程(一)创建1. 脱离父进程影响2. 脱离原会话组和进程组的影响3.修改进程工作目录4. 修改进程创建文件的掩码5. 关闭从父进程继承的文件描…

轻松搞定阿里云域名DNS解析

本文将会讲解如何设置阿里云域名DNS解析。在进行解析设置之前,你需要提前准备好需要设置的云服务器IP地址、域名以及CNAME记录。 如果你还没有云服务器和域名,可以参考下面的方法注册一个。 申请域名:《Namesilo域名注册》注册云服务器&…

[Cloud Networking] Layer Protocol (continue)

文章目录 1. STP / RSTP / MSTP Protocol1.1 STP的作用1.2 STP 生成树算法的三个步骤1.3 STP缺点 2. ARP Protocol3. DHCP Protocol3.1 DHCP 三种分配方式3.2 DHCP 攻击 4. IPSEC / MACSEC 1. STP / RSTP / MSTP Protocol 1.1 STP的作用 消除二层环路:通过阻断冗余…

大模型,也在卷价格

“百模大战”已从算力战、规模战蔓延到了价格战。 5月15日,字节跳动宣布豆包主力模型(小于等于32K)在企业市场的定价只有0.0008元/千Tokens,0.8厘就能处理1500多个汉字,比行业便宜99.3%;5月21日&#xff0…

【乐吾乐3D可视化组态编辑器】用开关控制巡检车和路灯

一、运动设备开关控制 3D组态编辑器地址:3D可视化组态 - 乐吾乐Le5le 1.在场景中新建模拟运动设备及控制面板:启动/停止 2.单击巡检车设备新建模拟动画 3.设置模拟动画属性 4.单击启动面板,新建交互事件 5.设置交互触发类型,新建…

WinForms 应用(.NET 8.0)使用ReportViewerCore.WinForms显示打印RDLC报表

在要WinForms 应用(.NET 8.0)中,显示RDLC报表,就要使用ReportViewerCore.WinForms。原来的ReportViewer只能在.NET Framework框架下运行。 1.ReportViewerCore.WinForms 程序包说明 SQL Server Reporting Services ReportViewer…

使用CodeGen进行程序综合推理

Program Synthesis with CodeGen — ROCm Blogs (amd.com) CodeGen是基于标准Transformer的自回归语言模型家族,用于程序合成,正如作者所定义的,它是一种利用输入-输出示例或自然语言描述生成解决指定问题的计算机程序的方法。 我们将测试的…

Mysql使用中的性能优化——单次插入和批量插入的性能差异

一般Mysql的客户端和服务端不在一台机器上,所以它们之间的通信需要通过网络进行。我们本次实验,希望抛开网络的影响,测试不同SQL方案在Mysql服务器上的执行效率的对比。于是我们使用“存储过程”来辅助测试。 结论 先上结论: 批…

HTML静态网页成品作业(HTML+CSS)—— 家乡南宁介绍网页(2个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有2个页面。 二、作品演示 三、代…