c++ string解析及其实现

news2025/1/21 22:07:41

因为字符串是固定长度,不好进行操作,因此c++就用类将字符串进行了封装让其变得方便实用。

要深刻了解string,我们必须要熟练掌握类的使用,如果还有疑问可以看这一篇博客:c++ 类 (要学习类这一篇就够了 )

string

#include<string>

string是需要引用头文件<string>的,同时使用官方命名空间std。

string的函数

首先就要了解string构造相关的函数:

默认,传参,拷贝,赋值,析构

对于迭代器版本我在下面再统一介绍

默认构造

默认构造就是构造一个"",里面只包含了'\0',但是它的大小是0,说明'\0'不作为它的长度。

拷贝构造

第一个拷贝构造就是传统的(里面有隐式类型转换,创造一个string的临时对象来进行拷贝,但是编译器把它进行优化了,相当于string a("123456")),第二个就是加了一个限定范围(从它的哪个地方开始拷贝,拷贝多长)。其实两个拷贝构造能合成一个缺省参数的。string(const string&str,size_t pos=0,size_t len=npos)


传参构造

这三个构造函数都可以归类于传参构造,接下来我们来举例一下:

第一个就是用一个字符串来进行构造,第二个是用字符串的前n个字符来进行构造,第三个是用n个c字符进行构造

其他构造方法
迭代器构造

具体在下面迭代器块详细介绍:

初始值设定项列表

这种是c++11出来的东西,主要是这样用:

赋值

赋值也很简单:

值得注意的就是赋值和拷贝都是深拷贝,需要重新申请堆区的内存。

析构

析构需要释放堆区的内存,这是重点。

迭代器

看这里需要知道迭代器是什么,可以看看这一篇:迭代器的介绍

里面详细介绍了string的迭代器,这里大致再复习一下。

迭代器有iterator(正向迭代器)、const_iterator(不可修改值的正向迭代器)reverse_iterator (反向迭代器) const_reverse_iterator(不可修改值的反向迭代器)

这里可以就看成指向数组内容的指针,只是typedef了一个别名而已。

我们可以通过解引用来访问值,通过调用begin(),end()来调用正向迭代器的开头和结尾,同时我们可以用rbegin(),rend()来调用反向迭代器的开头和结尾。

其实就把它成连续内存的特殊指针就行了,如果是反向迭代器就是反着走是正方向。

string的其他成员函数

我们分块来讲:

首先开头的迭代器成员函数我们已经了解到了

Capacity

了解函数前我们要大概了解string的成员变量是什么:

string的结构其实和顺序表是差不多的,用一个指针只想堆区内存的成员,然后是一个size记录当前字符串的长度,然后是用capacity记录申请内存的长度,即当前最大能存储字符的长度,超过这个长度就要扩容。

然后是;

size/length

这些是关于空间的函数,第一个就是获取当前的字符串实际长度。第二个和第一个是同义,为什么会有两个相同功能的函数是因为原先只有length的函数,但是并不适用于其他容器,其他容器空间不是线性的,所以用的size更加的宽泛,然后string为了和后面的统一就又加了size函数。

max_size

这里的max_size就是能够装多大的长度,一般是长度为len,size_t len=-1。因为类型转换会变成1111111111,就是size_t的最大储存长度。

resize

re一般在英语里面表示"再"的意思,这里就是再次定义空间意思,这里的空间不是capacity的空间重新申请,而是增加或减少size的长度。

首先是缩短:

void resize(size_t n)一般这个函数是用来缩减长度的。

缩短就是直接减少长度。

增长:

resize(size_t n,char c=0)

这里的n不是要增加或者减少多少长度,而是改变后的长度。第二个参量是增长要的字符,一般是缺省值'\0'

增长不会改变原有的内容,而是从末尾处用字符c开始增长。

这里我们发现它和字符串的打印还略有不同,不是到'\0'终止,而是继续打印('\0'是打印不出来东西的),这里是根据size来打印。

capacity

这个就是返回最大储存长度的值

如果size和capacity相等了就会扩容,那么扩容会有不同扩的方法,在vs上面是1.5倍扩:

这里看上去不是标准的二倍是没有吧'\0'算进去。

这里我们还发现在开始第一次是二倍扩的,这是因为我们开始的16长度不是在堆区申请的内存,而是在栈区的内存,如果满了就再申请堆区的。

如果在Linux下,就是2倍扩容。而且初始不会给内存。

reserve

这个就是重新定义capacity的长度,那么也有缩短和增长的问题,在VS和linux下面是略有不同的:

在vs上:

首先是增长,增长会根据1.5倍扩容来reserve ,假如你现在是64长度的capacity,那么你要扩到80,他会给你扩到96

然后是缩短:vs是不会进行缩短的,因为缩短也会进行重新内存申请,然后把原来的数据拷贝过去。可能考虑到这一点所以不缩。

在Linux上:

Linux上面就比较自由,你要它扩多少它就扩到多少,如果是缩短它也会缩,如果你让它缩的长度小于size会所到等于size为止。

clear

clear就是清除数据,只留一个'\0'

empty

这个函数是判断string是否为空

shrink_to_fit

这个函数就是让capacity缩到和size一样的长度。和linux的reserve的缩短一样的。

Element access

operator[]

重载[]方便像数组一样进行下标访问。

如果超出范围会assertv

at

这个和opertator[]的作用是一样的,唯一不同就是超出范围会抛异常不是assert

back

根据类是否const来返回最后一个数据的引用

front

同上面一样,除了这里返回第一个

Modifiers:

operator+=

这个就是在原串后面增加一个串的操作服重载:

前面三个好说,就是加string、数组、字符。

第四个是c++11的:

用一个括号括起来里面放数据的做法就是initializer_list类型

append

和+=重载是一样的,往后追加内容,但是有更多的操作:

使用是和string的构造函数一样的,只是一个是用指定内容构造一个是用指定内容追加在末尾。

push_back

这个就是往后面压入一个字符

assgin

assgin就是重新给string内容的意思,和resize不同的是,它是会将之前的值全面覆盖。

这里的8个重载也和构造函数的几个重载和append的7个重载一样的。(里面的右值引用我不讲,因为我还没学到,后面学到了再来补充)

insert

插入内容的意思,涉及的重载和上面的assgin、append、构造函数一样的。

支持只插入一个字符或者字符串

下面是举例:

erase

和insert函数是对应的

第一个参数就是传开始删除的位置,可以传迭代器,也可以传下标。第二个是终止的位置不传一般是删到末尾。

replace

顾名思义,是替换内容的意思,这里前两个参数

这些其实都是一个逻辑用法,前两个参数传要替换的区间,可以传下标区间,可以传迭代器区间;

后面参数其实和构造函数、append、insert传参是一个模式。

swap

swap函数是交换两个string的内容,但是它不是用的官方的普通swap。

我们用下面的代码模拟一下

红框的就是官方的常用swap,构造一个临时变量,然后再赋值,这样的操作给string将会有一次拷贝构造两次赋值重载,会有很大的时间损耗,每次都要开新空间。所以类里面实现是交换每个参量的值。为了防止有人用默认的swap,所以又写了一个全局的string专用swap函数(如果有现成的函数,和它同类型的模板是不会去实例化的,会直接用现成的)。

pop_back

就是删除最后一个元素。

String operations:

c_str

返回c类型的字符串。

data

跟c_str是差不多的,返回字符串

get_allocator

获取内存池,这里内存池是指先从堆区申请一大块内存,然后要内存申请就在内存池里面申请,增加申请的速度。

copy

将从pos下标开始的,长度为len的内容拷贝到s字符串上面去。

find

寻找对应的字符或者字符串,返回第一个字符的下标

rfind

rfind就是反向查找

find_first_of

这个函数就是find的加强版,输入一个字符串或字符,只要是里面其中之一的字符,就会返回。

举例:

要把所有aeiou的字符屏蔽掉。

find_last_of

这个就是反着开始进行find_first_of

find_first_not_of

这个就是找出了那几个字符其他的字符。

find_last_not_of 

这个就是反着进行find_first_not_of

substr

取出string里面从pos下标点,长度为n的数据并返回字符串

举例:

compare

进行比较,和strcmp的返回值一样的。

用的不是很多,因为可以用运算符重载

Member constants

这个和max_size是一个东西,返回可以创建string的最大长度

它其实是一个成员变量 是  const static size_t npos=-1。

Non-member function overloads(全局函数)

operator+

实现两个串的相加

逻辑运算符

这个很简单就不说了,这个比compare好用的多。但是这个没有compare的局部比较

operator<<和operator>>

这个就不用多说了,流插入和流提取。

getline

operator>>的流插入是默认空格和换行停止读取的,所以针对于"I love you"这种有空格的字符串就不能很好的运行。所以就有了getline

这里的delim就是遇到什么停止读取,默认是'\n'停止读取。

到这里所有和string相关的函数就说完了,大家可以理解性记忆。

string的实现

较为完善的string实现

首先我们写的string类是写在.h文件里的,因为在类里面的函数是内联函数,所以就直接在类里面写,如果遇到函数行数比较多的,就可以在.cpp里面写

我们可以自己创建一个命名空间来写我们的string类,与标准库里面的string类进行区分。

string我只实现一个简单版本的,没有内存池,没有vs里面的初始16长度的栈区内存,那么成员变量就有:char*_str size_t _size  size_t _capacity const static size_t npos=-1;

先是构造函数:

这里我们不将'\0'计入capacity中,所以我们申请内存要额外再给‘\0’申请一字节的空间。即new char[_capacity+1]

然后是一些其他的成员函数:

类外函数我们就只实现这三个,然后是迭代器的typedef。

一些比较长的函数就在另一个文件里面:

那么一个相对完整的string就模拟出来了。

面试里面简单string的实现

面试肯定不会让你实现一个这么长的string,只会让你将一些基础的功能实现出来。

那么我参考了陈皓的文章C++面试中string类的一种正确写法 | 酷 壳 - CoolShell来进行如下讲解:

首先我们可以不需要capacity和size这两个成员变量,只要进行简单的构造,赋值,交换,返回大小这些操作即可:

 

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

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

相关文章

Android 11(R)启动流程 初版

启动流程 bootloader会去启动android第一个进程Idle&#xff0c;pid为0&#xff0c;会对进程 内存管理等进行初始化。Idle还被称作swapper。Idle会去创建两个进程&#xff0c;一个是init&#xff0c;另外一个是kthread。 kthread会去启动内核&#xff0c;用户是由init进行启动。…

算法通关:017_1:二叉树及三种顺序的递归遍历

文章目录 题目思路代码运行结果 题目 二叉树及三种顺序的递归遍历 思路 代码 /*** Author: ggdpzhk* CreateTime: 2024-08-04** 二叉树及三种顺序的递归遍历* LeetCode 144. 二叉树的前序遍历* LeetCode 94. 二叉树的中序遍历* LeetCode 145. 二叉树的后序遍历* LeetCode 10…

sqli-labs靶场——第二关

1、判断注入类型 ?id1和?id2-1的页面一样所以是数字型 2、判断闭合类型 数字型没有闭合符号 3、order by查看有几列 当输入order by 4 时候页面变化&#xff0c;3的时候正常&#xff0c;所以是3列 4、union select联合查询查看回显 /sqli-labs/Less-2/?id-1 union sel…

ESP32使用MQTT协议通讯(EMQX)

一、背景介绍 前面完成了ESP32MicroPython环境的搭建01_ESP32 MicroPython开发环境搭建_eps32开发板-CSDN博客 现在想实现以下功能&#xff1a; 1.通过手机或电脑&#xff0c;远程给ESP32发送相关指令。 2.ESP32接到指令后&#xff0c;做出相应的高低电平输出。 这样就相当…

视频编辑SDK,底层架构合理,前端自定义程度高

如何高效、专业地制作出符合品牌形象、吸引目标受众的视频内容&#xff0c;成为了众多企业面临的共同挑战。美摄科技&#xff0c;作为视频编辑技术的先行者&#xff0c;以其卓越的视频编辑SDK&#xff08;Software Development Kit&#xff09;&#xff0c;为企业用户量身打造了…

进程状态都有哪些?

目录 前言&#xff1a; 进程的各个状态&#xff1a; 1、R状态&#xff08;进程运行状态&#xff09;和S状态&#xff08;休眠状态&#xff09; 2、T状态和t状态&#xff08;暂停进程&#xff09; 3、D状态&#xff08;磁盘休眠状态&#xff09; 4、Z状态&#xff08;僵尸状…

学习笔记 韩顺平 零基础30天学会Java(2024.8.2)

P447 五大运行时异常 P448 异常课堂练习 P449 异常处理机制 try-catch-finally throws(处理机制二选一)&#xff0c;如果没有显式处理异常&#xff0c;默认throws JVM处理异常直接输出异常信息&#xff0c;退出程序 P450 tryCatch 对于第一个细节&#xff0c;发生异常之后时try…

C语言快速入门及精通学习指南——手把手教零基础/新手入门(完整C语言学习笔记整理)

前言 作为一名拥有多年开发经验的码农&#xff0c;我的职业生涯涵盖了多种编程语言&#xff0c;包括 C 语言、C、C# 和 JavaScript。在这一过程中&#xff0c;我深刻地意识到扎实的基础对于编程学习的重要性&#xff0c;尤其是对于 C 语言这样一门核心语言来说。 出于对…

sgg快餐项目-3 项目

一、数仓架构 本项目的数据是事务数据&#xff0c;都存储在mysql数据库&#xff0c;如果是其他的项目&#xff0c;那数据可能会在文本、爬虫等。要使用相关的组件将数据导入到HDFS上。&#xff08;因为要把数据导入到hive做数据管理、存储和分析&#xff0c;而hive就是在hfds上…

2024年文件防泄密系统TOP3|遥遥领先的文件防泄密系统

古语有云&#xff1a;“密者&#xff0c;国之重器&#xff0c;不可不慎。” 在今日之数字化时代&#xff0c;信息的保密与安全&#xff0c;已然成为企业乃至国家生存与发展的基石。 随着数据泄露事件频发&#xff0c;文件防泄密系统的重要性愈发凸显。 2024年&#xff0c;随着…

数据存储与访问

一、文件存储读写 1.Android文件的操作模式 2.文件的相关操作方法 3.文件读写的实现 Android中的文件读写和Java中的文件I/O相同&#xff0c;流程也很简单&#xff0c;下面我们来写个简单的示例&#xff1a; PS:这里用的是模拟器&#xff0c;因为笔者的N5并没有root&#xf…

Go语言加Vue3零基础入门全栈班11 Go语言+gorm用户管理系统实战 2024年08月03日 课程笔记

概述 如果您没有Golang的基础&#xff0c;应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728Go语言操作MySQL开发用户管理系统API教程_20240729Redis零基础快速入门_20231227GoRedis开发用户管理系统API实战_20240730Mo…

工业人工智能真的能落地吗?

文章目录 前言Part1 聊聊技术1 人工智能、机器学习和深度学习的关系2 优化思想的一个案例 part2 聊聊业务3 工业人工智能与消费互联网人工智能的区别3.1 消费互联网中人工智能的应用3.2 为什么如此成熟的消费互联网人工智能扩展到工业场景那么难 4 工业互联网人工智能的发展方向…

wxPython中wx.adv.DatePickerCtrl用法

wx.adv.DatePickerCtrl是一个日期选择组件&#xff0c;支持键盘手工录入日期和弹出日历窗口选择日期两种方式。 一、组件样式 wx.adv.DP_SPIN &#xff1a; 只允许键盘手工录入和组件右侧上下箭头调整日期。 wx.adv.DP_DROPDOWN &#xff1a; 只允许健盘手工录入和组件右侧打开…

CentOS7 编译ffmpeg wasm库

1. 安装 emscripten 1)克隆 emsdk git clone https://github.com/emscripten-core/emsdk.git 2)cd 到emsdk 3)安装,按照官网的步骤(Download and install — Emscripten 3.1.65-git (dev) documentation) 4)验证 注意:如果emcc -v 报错: 提示是python脚本错误,是因为…

Qt Modbus 寄存器读写实例

一.线圈状态寄存器读写 项目效果如下 1. 写单个寄存器 MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); int addrui->spinBoxwirte_addr->value();int dataui->spinBoxwirte_data->value();int ret modbus_write_bit(mb,addr,d…

【Qt】Qt日志信息处理

Qt日志信息处理 一、介绍二、相关函数的使用介绍1. qInstallMessageHandle2. QtMsgType3. QMessageLogContext 三、一个简单示例 一、介绍 Qt有Info、Debug、Warning、Critical、Fatal五种级别的调试信息。 Info: 提示信息qDebug&#xff1a;调试信息qWarning&#xff1a;警告…

目标检测——X光安检数据集

1. OPIXray数据集&#xff08;2020&#xff09; 2. HIXray数据集&#xff08;2021&#xff09; 3. SIXray数据集&#xff08;2019&#xff09; 4. CLCXray数据集&#xff08;2022&#xff09; 5. PIDray数据集&#xff08;2021&#xff09; 6. GDXray数据集&#xff08;20…

C++-引用,inline,nullptr

一&#xff0c;引用 1.1引用的概念与定义 引用不是新定义⼀个变量&#xff0c;而是给已存在变量取了⼀个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同⼀块内存空间。 引用的使用方式如下&#xff1a; 类型& 引用别名 引用对象…

【带你入门生信】什么是生物信息学

生物信息学 生物信息学&#xff1a;利用应用数学、信息学、统计学和计算机科学&#xff0c;对生物学数据进行搜索&#xff08;收集和筛选&#xff09;、处理&#xff08;编辑、整理、管理和显示&#xff09;及分析&#xff08;计算和模拟&#xff09;&#xff0c;提取生物信息…