【STL】string的使用

放在专栏【C++知识总结】,会持续更新,期待支持🌹


STL简介

STL的诞生

STL为英文Standard Template Library的缩写,译为标准模板库是C++标准库的重要组成部分

  • 长久以来,软件届一直希望建立一种可重复运用的东西。所谓的泛型思想以及面向对象最主要的目的就是为了复用性的提升
  • 复用性需要建立在某种标准之上,而数据结构与算法却迟迟未能有一套标准,导致大量程序员被迫从事大量重复的工作
  • STL的出现实现了在数据结构与算法之间建立一套标准,并降低其耦合度。

STL具有多个版本:HP版本、P.J.版本、RW以及SGI版本,由于SGI版本在命名风格以及编程风格方面可读性更佳,所以后续一些学习都将参考该版本。

STL的组成部分

STL由六大组件构成,分别为:容器、算法、迭代器、仿函数、配接器、空间配置器。彼此之间可以组合套用。

接下来,我们学习的就是关于string相关使用。

string类

string简介

在C语言中,有整形、字符类型、浮点型等,但是=并没有字符串类型。而对于字符串,C语言中通常都是使用字符指针或字符数组来存储。但是字符指针指向的是字符常量,不可被修改,而字符数组又面临数组越界等情况。并且也不符合面向对象的思想。C++针对于此,string诞生。

如果我们仔细观察的话,就会发现,实际上string类是basic_string模板类使用char来实例化出来的一个类。对于basic_string模板类,这里不做过多介绍,有兴趣的可以搜寻相关文档。

 string的使用

(不要忘记包含头文件<string>

构造函数

string的构造函数有很多接口,没必要各个都掌握,否则学习起来会比较繁琐。(这也是C++被吐槽的原因之一,这么多接口,咋可能都记住)。我们只需要掌握其中一些即可,其余的可以翻阅文档。如下:

string提供的构造函数功能说明
string()构造空的string类对象,即空字符串
string(const char* str)用C语言格式的字符串,来构造一个string类对象
string(size_t n,char c)用n个字符,来构造一个string类对象
string(const string& str)拷贝构造

具体使用如下

#include<iostream>
#include<string>//头文件
//using namespace std;//也可以直接展开命名空间,后面就不需要声明string属于std这个域了

int main()
{
	std::string s1;               //空字符串构造
	std::string s2("hello world");//用C格式字符串构造
	std::string s3(10, 'a');      //10个a字符,来构造一个string对象

	std::string s4(s3);           //拷贝构造

	std::cout << "s1: " << s1 << std::endl;
	std::cout << "s2: " << s2 << std::endl;
	std::cout << "s3: " << s3 << std::endl;
	std::cout << "s4: " << s4 << std::endl;

	return 0;
}

运行结果如下:

 容量相关

string提供的有关容量的函数功能说明
size返回有效字符串的长度
length与size相同,推荐使用size
capacity空间总大小
empty字符串是否为空,空返回true,非空返回false
clear清空有效字符
reserve进行扩容,改变的是总空间的大小,直接影响capacity
resize对有效字符进行扩容,改变的是size的大小,可能会间接影响capacity

size与capacity

我们来看,size为有效字符的长度大小,capacity为总空间大小。两者并不相同。如下图:

clear与empty就不用多说了,这里需要注意的是,clear只是将有效字符的第一个字符设置成\0,不会改变总空间的大小,但是会影响size,因为size计算的是有效字符串的长度,遇到\0结束。

 reserve与resize

两者都是扩容,不同的是,reserve是改变总空间的大小,而resize改变的是有效字符的大小。如下:

reserve进行空间扩容时,采用异地扩容 。

可能有人也想我这么皮,用reserve缩容,看看会发生啥,如下:reserve不会进行缩容。 

resize

 resize则是将有效字符扩容成n个,如果不指定c,则默认用0来填充剩余空间,如果扩容后的有效字符超过了总空间的大小,则总空间会自动扩容。

VS与Linux扩容策略对比

如果细心的话,就会发现,我们在VS中进行扩容时,一开始时数据存放在15大小的_buf数组中,后来在扩容超过该数组空间时,才又开辟额外空间。

我们可以写如下代码来进行验证一下:

int main()
{
	string s;
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

VS扩容策略

  1. 数据size小于15时,存放在buf数组中。
  2. 当数据大于15时,先2倍扩容,后续再进行扩容时以1.5倍进行扩容

Linux扩容策略

  1. 不存在buf数组,默认空间大小为0
  2. 从1开始,严格遵守2倍扩容

实际上VS的策略更加合理一些,因为实际中string的大小不会太大,给个15大小的数组,一般是够用的。而Linux频繁的扩容,会导致内存碎片问题,因此VS策略会更加合理一些。另外,我们在使用string时,如果能提前计算出所需要的空间,直接reserve提前扩容,会提高一定的运行效率。

string类对象的访问以及遍历

1.[]下标访问

由于string对[]进行重载,所以支持[]进行访问,就像数组下标一样。使用也很简单,如下:

 2.迭代器

什么是迭代器?

首先我们来谈一谈迭代器是个啥东西,迭代器既然可以作为六大组件之一,那么一定有它的过人之处。我们先来看一下迭代器在书中《STL源码剖析》的定义:

 

 简单来说,就是用一个对象,来模拟一个指针的行为,从而实现对各个容器中成员的访问

在string,或者vector(实际上就是一个数组)中,我们可以将它简单的想象成一个指针,指针++,表示访问下一个元素的地址,*解引用,表示访问该位置的成员。(当然,它并不是一个指针,因为像链表、树形结构中,各个元素之间的地址并不是紧密相连,后续遇到再仔细讲解,这里就简单理解为指针)。

回归正题,这里用迭代器进行成员访问,如下:

 reverse_iterator为反向迭代器,顾名思义可以倒着访问,使用如下:

当然,string还存在const_iterator与const_reverse_iterator。看名字也可以看出来,不可对成员进行修改。用法与上面一样。具体迭代器的细节将放在后面list章节再继续探讨。

3、范围for

范围for的底层实际上是迭代器,用法也很简单,在前面章节已经讲解过。

 

string类对象的修改操作

插入与删除

我们查阅官方文档,发现有大量的接口供我们使用,这里我就只讲某个函数的其中一个来讲解(实在是太多,不得不吐槽)

string支持的插入函数功能含义
push_back尾插字符
append追加字符串
+=追加字符串
insert插入操作

这些接口都很简单,用法如下:

 删除erase,用法也很简单,这里就不做过多演示。大家可以自己去试着玩一玩。

查找find

 find默认从0下标开始,查找一个字符或者字符串,找到后返回该字符所在的下标。找不到返回npos。npos实际上就是-1,而size_t是无符号整形,所以这里的npos代表整形最大值。用法如下:

 string提供的接口实在是太多了,大家自行可以去网站https://cplusplus.com/reference/查找。这里我就不做相关演示了。

string的模拟实现

为了能更好的理解底层的实现,我们可以参照STL中string的源码实现,来自己实现一个简单的string,从而加深对string的理解。源码可能会复杂难懂,推荐书籍《STL源码剖析》,里面会有一些关键标注。当然我们在实现时没必要面面俱到,实现大体即可。

以下链接内为我个人实现的一个简单string,内部含有个人注释,如有不解,可联系交谈:

string类的模拟实现练习 · ede63fa · 齐敦炎/C++学习所用仓库 - Gitee.com


end.

生活原本沉闷,但跑起来就会有风!🌹

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

元宇宙又“死”了!Epic老板:你当6亿用户是摆设?

“扎克伯格花了数年时间试图让Metaverse成为现实&#xff0c;但现在它已被AI取代&#xff0c;并走向科技创意的坟墓。”一篇表达“元宇宙已死”的文章近期在推特上引发热议&#xff0c;而游戏制作公司Epic Games CEO Tim Sweeney的还击更是让这个话题热上加热。 “搞一次在线守…

远程桌面基本原理

远程桌面基本原理 远程桌面是一种技术&#xff0c;它允许用户通过互联网或局域网远程访问另一台计算机的桌面。这种技术可以让用户在不同的地方使用同一台计算机&#xff0c;或者在同一地方使用不同的计算机。远程桌面技术在现代计算机应用中发挥着重要的作用&#xff0c;本文将…

数据结构(堆)

文章目录 一、概念二、堆的使用三、PriorityQueue 介绍3.1 PriorityQueue 的特性3.2 PriorityQueue 的方法3.3 集合框架中PriorityQueue的比较方式 四、堆的应用 一、概念 1.什么是优先级队列 队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数…

发明专利公开 -- CSS动画精准实现时钟

上一篇【setTimeout不准时&#xff0c;CSS精准实现计时器功能】的博文&#xff0c;最后提到了通过 CSS 动画实现计时器的方式。 本文详情描述如何通过 CSS 完整实现时钟效果&#xff0c;这也是团队 21 年专利的一项内容&#xff08;专利公布号&#xff1a;CN114003087A&#x…

Agisoft Metashape 空三导入Photomod

Agisoft Metashape 空三导入Photomod 文章目录 Agisoft Metashape 空三导入Photomod前言一、Metashape空三成果导出1.1导出PAT-B空三格式1.2. 导出相机文件二、Photomod空三成果导入2.1导入PAT-B空三格式2.2导入相机文件前言 本文讲解将Agisoft Metashape的空三成果导入Photom…

【C++初阶】:类与对象(下)

类与对象 一.再谈构造函数1.初始化列表&#xff08;构造函数的一部分&#xff09;2.explicit关键字 二.static成员三.友元1.友元函数2.友元类 四.内部类五.匿名对象六.再次理解类与对象 一.再谈构造函数 1.初始化列表&#xff08;构造函数的一部分&#xff09; 我们可以直接在…

Java 版企业工程项目管理系统平台(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

揭开Facebook数据抓取的面纱,深入了解其运作机制

在互联网时代&#xff0c;数据是一切的基础。而社交媒体作为数据存储与传输的重要渠道&#xff0c;其数据价值不言而喻。 那么&#xff0c;Facebook数据抓取是如何进行的呢&#xff1f; 1.API接口 首先&#xff0c;我们需要了解一些基本的概念。Facebook的API&#xff08;Ap…

基于AT89C51单片机的温度检测报警设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87777752?spm1001.2014.3001.5503 源码获取 主要内容&#xff1a; 基于51单片机设计一个温度检测报警器&#xff0c;至少具有以下功能&#xff1a;温度的检测和超…

计网U+选择题知识点

第一章U 1.Internet 网络本质上属于&#xff08; 分组交换&#xff09;网络。 2.(网络层发送的是分组) 3.在 OSI 参考模型中,自下而上第一个提供端到端服务的是(传输层 )。 4.APRANET 5.三类大家很熟悉的网络是&#xff08;电信网络&#xff0c;有线电视网络&#xff0c;计算机…

【JMM】保证线程间的可见性,还只知道volatile?

本文目录 前言 举例&#x1f330; 情形1 int->Integer 情形2 System.out.println() 情形3 storeFence() 情形4 Thread.yield() 情形5 LockSupport.unpark() 情形6 增长循环内代码执行时间 总结分析 volatile分析 字节码解释器实现 模版解释器实现 其他情形…

自动化测试的生命周期是什么?

软件测试发展到今日&#xff0c;已经逐渐标准化且能力更强&#xff0c;其流程每天都在发展。测试人员的技术熟练程度对于整个测试阶段的成功来说至关重要。测试不再意味着仅仅发现错误&#xff1b;它的范围已经扩大&#xff0c;从任何开发项目开始就可以看出它的重要性。 当谈论…

Parker派克伺服电机有哪些优势特点?如何选型?

一、什么是伺服电机&#xff1f; 伺服电机是一种可以通过控制器精确地控制位置、速度和加速度的电机&#xff0c;主要由电机、编码器和控制器三部分组成&#xff0c;具有高转矩、高精度、快速响应和低转速稳定特性&#xff0c;能够在负载扰动、电压变化及机械特性变化下保持较…

分布式搜索引擎es 面试突击

es elastocsearch 倒排索引是在数据查询之前建立&#xff0c;在查询的时候可以直接通过关键词定位到文档内容。用空间换时间 分布式架构原理说一下&#xff1f; es底层是基于lucene来的 大概就是一个用于全文检索的jar包 用es来做分布式的搜索引擎 可以承载一秒钟几千的…

基于分布鲁棒联合机会约束的能源和储备调度(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

CloudCompare二次开发之如何通过PCL进行点云滤波?

文章目录 0.引言1.CloudCompare界面设计滤波(filter)按钮2.PassThrough直通滤波器3.VoxelGrid体素滤波器4.UniformSampling均匀采样5.StatisticalOutlierRemoval统计滤波器6.RadiusOutlierRemoval半径滤波器7.ConditionRemoval条件滤波器8.ProjectInliers投影滤波器9.ModelOutl…

写给程序员Android Framework 开发,

前言 在 Android 开发者技能中&#xff0c;如果想进大厂&#xff0c;一般拥有较好的学历可能有优势一些。但是如果你靠硬实力也是有机会的&#xff0c;例如死磕Framework。Framework 知识广泛应用在Android各个领域中&#xff0c;重要性显而易见。 成为一名Android Framework…

maven学习总结

生命周期 每个生命周期的各个环节都是由各种插件完成&#xff01;&#xff01;&#xff01;Maven有三个相互独立的生命周期&#xff08;Maven的这三个生命周期不能看成一个整体&#xff09;&#xff01;&#xff01;&#xff01; 我们在开发中描述的项目的生命周期&#xff0…

互联网营销之何谓真需求-想知道如何挖掘真需求看这篇就对了

互联网营销思维是以爆品为核心的迭代思维&#xff0c;本文结合“生日蛋糕”、“方便面”、“蜜雪冰城”几个小例子&#xff0c;以及我们具体的工作&#xff0c;展开聊聊什么是“真需求”。 1. 互联网营销和传统营销的区别 1.1 传统的营销思维&#xff1a; “定位4P&#xff0…

如何修复d3dcompiler_47.dll缺失?多种解决方法分享

在使用Windows操作系统的过程中&#xff0c;有时候会遇到d3dcompiler_47.dll缺失的情况。这个问题可能会导致某些应用程序无法正常运行&#xff0c;因此需要及时解决。本文将介绍如何修复d3dcompiler_47.dll缺失的问题。 一.什么是d3dcompiler_47.dll D3dcompiler_47.dll是Di…