【C++】从string开始了解STL

news2024/11/27 16:44:41

文章目录

  • 1.初识STL
    • 1.什么是STL
    • 2.STL的版本
    • 3.STL的六大组件
  • 2.string
    • 1.string类模板
    • 2.string类的构造函数
    • 3.string内部数据访问
    • 4.string的遍历
    • 5.string类的迭代器
    • 6.string的Capacity相关接口
    • 7.string的修改相关接口
    • 8.其他接口

1.初识STL

1.什么是STL

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架

2.STL的版本

  • 原始版本

    Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本–所有STL实现版本的始祖

  • P.J.版本

    由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异

  • RW版本

    由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般

  • SGI版本

    由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码,主要参考的就是这个版本

3.STL的六大组件

image-20230413011601095

对于STL的学习,这里推荐一个网站cplusplus.com

2.string

接下来就要正式进入到对STL的学习中啦,在对STL的学习过程中,需要注意的是

第一、熟悉库里面的STL的各种类模板的常用接口

第二、尝试去模拟实现库里面的类模板

注:在过程中,我们可能会遇到一些没有办法解决的问题,此时将会去查库里的源码,由于各个库中的实现方式不太一样,所以,在这里定一下,我们将会参考SGI版本的代码,结合侯捷老师的STL源码剖析去模拟实现。

1.string类模板

我们打开上文中推荐的网站,搜索string,会发现我们平常用的string其实是basic_string<char>,是类模板basic_string实例化出来的char类。

image-20230413164133833

basic_string是一个类模板,可以通过传入不同的类型参数实例化出不同的类。

image-20230413164426971

那么,对于string,为什么要使用一个类模板呢,在C语言中,对于字符串都是能够存放char类型的数据就可以了?

这是因为编码的问题,我们知道,在计算机中存放的数据都是0和1,为了让数据转换成人能看懂的东西,人们把特定的01序列给定义成某个字符,按照这种方式可以将计算机中的数据翻译出来,这就是编码,最初的编码方式就是将一些符号和大小写的26个字母与01序列对应,这就是ASCII码。

现在的常见编码方式

  • ASCII码

    美国信息交换标准代码,是计算机存值和文字符号的对应关系,只有256个字符

  • Unicode

    万国码,是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码包括了utf-8,utf-16,utf-32

    utf-8兼容了ASCII,utf-8使用比较普遍,也比较节省空间

  • gbk

    gbk即国标,针对中文而设计的编码,采用双字节编码

2.string类的构造函数

首先,一个类中必不可少的就是构造函数,我们来看一下string类的构造函数有什么

image-20230413210421519

以上就是string的所有构造函数了,接下来让我们通过代码来实验一下:

void Test_Construct()
{
	char str[] = "hello string";//创建一个C语言的字符串
	string s1;//默认构造函数,不用传递任何参数,最终是s1中只有一个\0
	string s2(str);//使用C语言的字符串构造一个string类型的对象
	string s3(s2);//使用s2拷贝构造一个string类型的对象
	string s4(s3, 2, 5);//使用s3中的第二个位置开始长度为5的子串构造对象
	string s5(str, 8);//使用C语言的字符串构造一个指定长度的string类型
	string s6(10, 'a');//使用指定字符构造一个长度为10,内容为a的对象
	auto first = s2.begin();
	auto last = s2.end();
	string s7(first, last);//使用迭代器区间构造一个[first,last)的对象
	cout << "s1: " << s1 << endl;
	cout << "s2: " << s2 << endl;
	cout << "s3: " << s3 << endl;
	cout << "s4: " << s4 << endl;
	cout << "s5: " << s5 << endl;
	cout << "s6: " << s6 << endl;
	cout << "s7: " << s7 << endl;
}

运行上述代码,结果是:

image-20230413212541978

在上面的函数原型中,好像发现了一个之前没见过的东西,npos,什么是npos呢?查一下文档

image-20230413212851969

可以看到npos是在类中定义的一个公共的静态成员常量,这个常量定义的值为-1,但是由于常量的类型是size_t,即unsigned int,所以表示的此类型可能的最大值。我们理解成字符串的结尾即可。

由于npos是string类中的成员常量,所以在使用npos的时候需要指定类域,即string::npos.

3.string内部数据访问

image-20230413233845379

可以看到,对于数据访问,string提供了4个接口,其中两个是C++11新增的,看名字也可以得出,是获得字符串首元素和最后一个元素的,不常用,所以在此不过多赘述。我们主要关注at和operator[]这两个接口。

image-20230413234409535

image-20230413234429978

这两个接口都是能够拿到指定位置的值,其中operator[]是对[]的运算符重载。可以看到两个接口都重载了普通版本和const版本,用来应对权限放大的问题。

void Test_Element()
{
	string s = "hello string";
	cout << s.at(4) << endl;
	cout << s[4] << endl;
}

image-20230414000051982

4.string的遍历

对于string的遍历,我们有以下几种方法:

  1. operator[]
  2. 范围for
  3. 迭代器
void Test_Element2()
{
	string s = "0123456789";
	//operator[]
	for (size_t i = 0; i < s.size(); ++i)
	{
		cout << s[i] << " ";
	}
	cout << endl;
	//范围for
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	//迭代器
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

image-20230414001152126

5.string类的迭代器

在遍历中,我们讲到了迭代器的方式遍历字符串,那么迭代器是什么?为什么要有迭代器的存在?

迭代器是通过一种普适的方式去访问所有支持遍历的容器,迭代器的行为上像指针,但是本质上不全是指针

在string类中,原生指针就已经能够支持迭代器的行为,所以string的迭代器就是元素类型的指针。

image-20230413213824032

可以看到string提供了很多中不同的迭代器,我们可以将它们分类

1. 正向迭代器

begin和end,begin返回的是字符串的开头位置,end返回的是最后一个有效数据的下一个位置,即迭代器是前闭后开的*[begin,end)*

image-20230414001904042

image-20230414001919818

可以看到,不管是begin还是end都重载了const版本用来应对权限变化的问题。

2. 反向迭代器

反向迭代器与正向迭代器的用法完全一致,只是调用反向迭代器的时候,遍历数据的顺序是反的。

void Test_Iterator()
{
	string s = "0123456789";
	cout << "正向迭代器" << endl;
	string::iterator it1 = s.begin();
	while (it1 != s.end())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
	cout << "反向迭代器" << endl;
	string::reverse_iterator it2 = s.rbegin();
	while (it2 != s.rend())
	{
		cout << *it2 << " ";
		++it2;
	}
	cout << endl;
}

image-20230414002535594

3. const迭代器与const反向迭代器

这四个迭代器接口都是C++11为了规范代码而增加的,但是其实在前面四个接口中已经重载了const版本,所以这四个基本用不上,就不过多介绍了,使用方法和前面的是完全一致的。

6.string的Capacity相关接口

image-20230414002824152

在这么多接口中,我们最常用的有:

  • size:返回字符串长度
  • resize:重新设定字符串长度
  • capacity:返回字符串容量
  • reserve:重新设置字符串容量,如果传入的参数小于capacity则不做任何操作,如果大于capacity就开辟一段容量为n的空间,将原数据拷贝进来,然后释放原空间。
  • empty:返回字符串是否为空

其余的一些接口不常用,了解即可。

void Test_capacity()
{
	string s = "0123456789";
	cout << "size" << s.size() << endl;
	cout << "capacity" << s.capacity() << endl;
	s.reserve(20);
	cout << "capacity" << s.capacity() << endl;
	s.resize(5);
	cout << "size" << s.size() << endl;
	if (!s.empty())
	{
		string::iterator it1 = s.begin();
		while (it1 != s.end())
		{
			cout << *it1 << " ";
			++it1;
		}
		cout << endl;
	}
	else
	{
		cout << "string is empty" << endl;
	}

}

image-20230414003555655

7.string的修改相关接口

image-20230414003646756

其中,常用的有

  • operator+=:追加字符串,其中有三个重载,分别是追加字符串(复用append),追加C类型字符串(复用append),追加单个字符(复用push_back)
  • insert:在某个位置插入字符或者字符串
  • erase:在某个位置删除字符或者长度为len的字符串
void Test_Modify()
{
	string s = "abcdefg";
	cout << s << endl;
	s += 'h';
	cout << s << endl;
	s += "ijklm";
	cout << s << endl;
	s.insert(5, 1, 'A');
	cout << s << endl;
	s.erase(5, 1);
	cout << s << endl;
}

image-20230414004529694

8.其他接口

  • c_str:以C语言字符串的方式返回一个字符指针(由于Linux是用C语言写的,在字符串的读写中,不支持string类型的读写,所以提供此接口)
  • find:在字符串某一段位置中找到某个值,如果找到了就返回下标,否则返回npos
  • getline:读取缓冲区的数据直到遇到换行符,这是为了防止出现cin遇到空格停止读取,无法将后续内容放入同一个字符串中
  • operator>>和operator<<:重载流插入和流提取,使字符串也支持cin和cout的用法

写在最后:

1. 由于这是第一次接触到STL,所以将很多的成员函数接口讲解的比较细致,后续的STL容器的接口将会省略掉一些重复的和相似性很高的函数。
2. 关于某个类的使用,是不可能用一篇博客说明白的,还是要在实践中学习,多看看文档里的内容

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

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

相关文章

Kotlin在Android开发中的应用与实践

Kotlin在Android开发中的应用与实践 通过本篇文章你将了解到下面内容&#xff1a; 介绍Kotlin语言&#xff1a;简述Kotlin语言的背景、特点和优势&#xff0c;为什么Kotlin在Android开发中变得越来越流行。 Kotlin与Java的对比&#xff1a;对比Kotlin和Java在语法、编程范式、…

规模化敏捷框架:Scrum@Scale

Scrum 敏捷方法有助于团队成员之间更有效地合作&#xff0c;实现共同的业务目标。但是当一个组织想要扩展 Scrum 方法到更多的团队时&#xff0c;应该如何实施&#xff1f;Scrum 仅为单团队开发、交付和运维产品提供了一个框架&#xff0c;而 ScrumScale&#xff08;SS&#xf…

多模态 AI 开发者召集令|4月22日@深圳,等你参加!

四月春暖花开&#xff0c;Jina AI 联合好朋友 OpenMMLab 一起&#xff0c;共同举办第八期「中文社区面对面」活动&#xff0c;将于 4 月 22 日&#xff08;周六&#xff09;下午在 Alpha Bay 深圳智汇港湾孵化器举行。本活动也得到了亚马逊云科技 User Group深圳、Xtreme1 的大…

C++ std::cin

C std::cin相关概念使用1. 一个常见的使用场景&#xff1a;2. 用于静态对象的构造和析构函数中&#xff0c;访问标准输入/输出流是安全的。3. 作为 *while* 语句的条件4. 配合 *get*、*getline* 使用相关概念 istream 一个class&#xff0c;提供输入操作。cin 一个 istream 对…

javaweb游戏代练网站设计与实现

目 录 第1章 绪论 5 1.1 选题的依据及意义 5 1.2 国内外现状研究 6 1.3 研究目的 6 第2章 设计技术与开发环境 7 2.1 相关技术介绍 7 2.1.1 JSP简介 7 2.1.2 B/S模式分析 8 2.1.3 mysql简介 9 2.2 开发环境介绍 9 2.2.1 Myeclipse简介 9 2…

魔镜魔镜告诉我,如何挑选靠谱的硬件方案!

随着传统健身房半胁迫顾客进行数万元的预售、办卡后&#xff0c;分分钟遁地跑路的新闻已经在大家心中留下了深深的烙印&#xff0c;再加上良莠不齐的教练、器材质量、永远无法抢到的健身课、以及办卡之后就被“打入冷宫”……可真是苦了每一个无处安放的运动灵魂啊&#xff01;…

XCODE14生成的APP制作成IPA

1.用XCODE14生成Archives存档包 2.在Finder中显示 3.显示包内容 4.双击进入Products 5.双击进入Applications 6.复制生成的.App文件到Playload文件夹 压缩Playload文件夹成zip 重命名zip为ipa 在弹出 的 提示中 选择 Use .ipa 重命名IPA文件为自己的命名

【vscode】SSH连接远程服务器Host/容器

目录 1. 连接远程服务器 1.1 确保远程服务器Host上ssh打开 1.2 本地主机 1.2.1 安装ssh-client 1.2.2 安装vscode插件 1.2.3 通过密钥完成身份认证 1.2.4 SSH连接配置 2. Python代码跳转 3. C代码跳转 4. Git 历史记录 5. 连接远程服务器上的Docker容器&#xff08;易…

radmin远程控制软件怎么样,有没有替代品

Radmin 是流行的、屡获殊荣的安全远程控制软件&#xff0c;它使您能够在远程计算机上实时工作&#xff0c;就像使用它自己的键盘和鼠标一样。 您可以从多个地方远程访问同一台计算机&#xff0c;是网络和管理类别中流行的远程桌面工具。 Radmin 是外国软件&#xff0c;在国内使…

Unity协程和线程的区别深入理解(附实验展示)

Unity协程和线程的区别附实验展示写在前面协程、进程、线程的概念进程与线程的区别协程与线程的区别实验1&#xff1a;协程中执行普通函数实验2&#xff1a;协程中开启另一个协程实验3&#xff1a;协程中开启WWW请求实验4&#xff1a;一个脚本中多个协程访问临界资源实验5&…

车载以太网基础篇之Eth Driver

车载以太网基础篇之Ethernet Driver前言 首先&#xff0c;请问大家几个小小问题&#xff0c;你清楚&#xff1a; 你知道Eth Driver模块的主要作用是什么吗&#xff1f;EthDriver与以太网控制器&#xff0c;以太网收发器&#xff0c;都有哪些关系呢&#xff1f;Eth Driver的常…

java虚拟机反射机制

&#xff08;1&#xff09;Java虚拟机反射机制的定义&#xff1f; Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功…

苍穹最终一致性使用

适用场景 最终一致模式可以保证跨数据库或跨节点更新时的数据一致。它会以1个更新操作为基准&#xff0c;注册多个其它更新操作&#xff0c;最终保证所有更新都成功&#xff0c;实现分布式事务的弱一致性。可以适用一个更新适用多个场景(跨云、跨库、跨系统) 工作原理 1、在第…

4月17日第壹简报,星期一,农历闰二月廿七

4月17日第壹简报&#xff0c;星期一&#xff0c;农历闰二月廿七坚持阅读&#xff0c;静待花开1. 风云三号G星顺利入轨&#xff01;我国成功发射首颗主动降水测量卫星&#xff08;能探测到毛毛雨般的降水&#xff09;。2. 四次出舱&#xff01;神舟十五号乘组刷新单个乘组出舱活…

Opencv c++ 图片截取不规则ROI区域

做目标检测的很多时候&#xff0c;需要我们选择一个相对固定的区域来识别目标。 思路很简单&#xff0c;适合相机固定&#xff0c;ROI变化不大的场景。 1、原图备份后先截取不规则的ROI区域&#xff0c;其他区域置为黑背景&#xff0c;检测识别效果 2、在原图上&#xff0c;将…

全新适配鸿蒙生态,Cocos引擎助力3D应用开发

一、适配HarmonyOS背景 HarmonyOS 3.1版本自发布以来&#xff0c;备受广大开发者的好评&#xff0c;同时也吸引了鸿蒙生态众多伙伴的青睐。 鸿蒙生态所强调的智慧全场景、多端联动与跨设备流转等能力&#xff0c;与Cocos所具有的跨平台、低功耗、高性能三大核心特点不谋而合。C…

银河麒麟服务器ky10 sp3 x86编译安装postgresql(包含uuid)

目录 下载 编译安装 目录说明 脚本文件说明 压缩包说明 脚本代码 下载 官网 PostgreSQL: The worlds most advanced open source database 源码下载地址 PostgreSQL: File Browser 有多个版本可以选择&#xff0c;我选择的是10.23 点击下载即可 我下载好之后把他上传到…

Qt网络编程 (udp广播和接收例)

大纲概述senderreceiver演示概述 使用两个项目 1 sender 用来广播"hello world";2 receiver 用来接收广播信息 sender 1 创建Qdialog类2 在sender.pro 中添加 QT network 一行代码3 在sender.h 中声明类 class QUdpSocket;在声明一个私有对象QUdpSocket *sender;…

ASEMI代理AD8226ARZ-R7亚德诺(ADI)车规级AD8226ARZ-R7

编辑&#xff1a;ll ASEMI代理AD8226ARZ-R7亚德诺&#xff08;ADI&#xff09;车规级AD8226ARZ-R7 型号&#xff1a;AD8226ARZ-R7 品牌&#xff1a;ADI /亚德诺 封装&#xff1a;SOIC-8 批号&#xff1a;2023 安装类型&#xff1a;表面贴装型 引脚数量&#xff1a;8 类…

VS 创建ATL组件(C++)

目录1、新建ATL项目2、添加接口类、实现接口方法3、创建自己的方法。在头文件Add.h中添加声明4、在源文件Add.cpp中添加函数实现5、在MyComTest.idl中添加方法接口设置&#xff0c;如interface IAdd:IDispatch中所示。6、解决方案配置选择release, 平台选择x64,生成。MyComTest…