【STL】string的使用

news2024/11/25 21:37:11

放在专栏【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.

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

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

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

相关文章

首个支持RWA交易的订单簿DEX-PoseiSwap,即将开启IEO

随着 DeFi 世界的发展&#xff0c;越来越多的链上协议支持以合成资产的方式&#xff0c;将传统金融资产以加密资产的形式映射至链上&#xff0c;包括美股、黄金期货等等&#xff0c;虽然这种方式进一步帮助投资者&#xff0c;以非许可的形式丰富了投资标的&#xff0c;但这种方…

GraphPad Prism 9.5.1 for Mac 操作简便功能强大且实用的医学绘图分析工具

GraphPad Prism简介 GraphPad Prism是一款非常实用的统计软件&#xff0c;其功能非常强大&#xff0c;能够帮助用户进行各类科研数据的处理和分析&#xff0c;快速绘制出各种专业的图像和数据报告。 GraphPad Prism软件的用户界面非常友好&#xff0c;易于学习和操作&#xf…

azkaban 安装 使用

目录 拷贝安装包 解压 改名 修改MySQL配置文件 创建数据库 导入数据表 修改配置文件 修改azkaban-exec下面文件 修改azkaban.properties文件 修改 commonprivate.properties 文件 修改MySQL的jar包 启动 azkaban-exec 修改azkaban-web下面文件 修改azkaban.prop…

Amazon EKS 上有状态服务启用存储加密

1.背景 用户通过 Deployment, Replication Controller 可以方便地在 Kubernetes 中部署一套高可用、可扩展的分布式无状态服务。这类应用不在本地存储数据&#xff0c;通过简单的负载均衡策略可实现请求分发。 Deployment 以及 Replication Controller 是为无状态服务而设计的…

关于Alibaba开发手册中提到的Manager层解析(对于传统MVC三层架构的改进)

Manager层的理解 MVC三层架构 MVC&#xff08;Model View Controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;它把软件系统分为模型、视图和控制器三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码&#xff0c;将业务逻辑聚集到一个部件里面…

scanf函数的用法

有时候刷题经常遇到如下这种输入&#xff1a; 1 2 3 4 ...... 就是不知道什么时候结束输入&#xff0c;反正就是一直在输入&#xff0c;这个时候怎么写呢&#xff1f;我们知道 scanf()的返回值是成功赋值的变量数量, 发生错误时返回EOF. 看如下代码&#xff1a; #include<st…

mysqlbinlog 生产环境问题排查实践

binlog 简介 MySQL 的二进制日志是通过二进制文件形式记录的&#xff0c;可以通过以下方式设置其格式&#xff1a; 打开 MySQL 配置文件&#xff08;my.cnf&#xff09;&#xff0c;找到 [mysqld] 段&#xff0c;添加以下语句以开启二进制日志功能&#xff1a; log-bin /pat…

Git 工作原理和分支管理

Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理 Git工作原理 Git 会把仓库中的每次提交串成一条时间线&#xff0c;这条时间线就是一个分支。在 Git 里&#xff0c;每个仓库都会有一个主分支&#xff0c;即master分支。HEAD…

2023面试自动化测试面试题【含答案】,建议收藏

1、你做了几年的测试、自动化测试&#xff0c;说一下 selenium 的原理是什么&#xff1f; 我做了五年的测试&#xff0c;1年的自动化测试&#xff1b; selenium 它是用 http 协议来连接 webdriver &#xff0c;客户端可以使用 Java 或者 Python 各种编程语言来实现&#xff1b…

路径规划算法:基于蜻蜓算法的路径规划算法- 附代码

路径规划算法&#xff1a;基于蜻蜓优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于蜻蜓优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法蜻蜓…

MyBatis项目的创建和使用

什么是MyBatis? MyBaits是一个更简单的完成程序与数据库交互的工具。MyBatis将复杂的JDBC进行了封装&#xff0c;让使用者可以通过简单的xml和注解对数据库进行记录。 MyBatis的执行流程 创建MyBatis项目 添加依赖 还是SpringBoot的创建流程&#xff1a;SpringBoot项目创建…

SpringMvc笔记-教程-快速回忆

title: SpringMvc笔记 date: 2023-05-14 09:50:02 categories: 后端Java tags:JavaSpring 三层架构&#xff1a; web层主要由servlet来处理&#xff0c;负责页面请求和数据的收集以及响应结果给前端service层主要负责业务逻辑的处理dao层主要负责数据的增删改查操作 MVC设计…

点餐小程序实战教程03-店铺信息展示

目录 1 创建模型应用2 创建用户3 创建自定义应用4 创建页面5 页面搭建6 定义变量7 数据绑定8 绑定事件9 预览发布总结我们上一篇设计了店铺信息数据源,并且录入了测试数据,本篇我们就介绍一下店铺信息展示功能的开发。 1 创建模型应用 我们在上篇讲解的是通过数据源的管理数…

【redis】redis经典五大类型源码及其底层实现

【redis】redis经典五大类型源码及其底层实现 文章目录 【redis】redis经典五大类型源码及其底层实现前言一、面试题redis数据类型的底层数据结构阅读源码的意义 二、在哪找redis的源码&#xff1f;三、SRC下的源码该怎么看&#xff1f;1、redis基本的数据结构&#xff08;骨架…

路径规划算法:基于樽海鞘算法的路径规划算法- 附代码

路径规划算法&#xff1a;基于樽海鞘优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于樽海鞘优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法…

桂院校园导航小程序 静态项目 二次开发教程 1.0.1

Gitee代码仓库&#xff1a;桂院校园导航小程序 GitHub代码仓库&#xff1a;GLU-Guide 先 假装 大伙都成功安装了静态项目&#xff0c;并能在 微信开发者工具 和 手机 上正确运行。 接着就是 将项目 改成自己的学校。 代码里的注释我就不说明了&#xff0c;有提到 我的学校 …

现代软件测试中的自动化测试工具

自动化测试的重要性和优势 引言&#xff1a;随着软件开发的不断发展&#xff0c;自动化测试工具在现代软件测试中扮演着重要角色。提高效率&#xff1a;自动化测试可以加快测试流程&#xff0c;减少人工测试所需的时间和资源。提升准确性&#xff1a;自动化测试工具可以减少人…

python3 爬虫相关学习3:requests.get(url)的各种属性

目录 1 requests.get(url) 的各种属性 1.1 response.text 1 requests.get(url) 的各种属性&#xff0c;也就是response的各种属性 接触的requests模块的常用功能&#xff1a;一般把 response requests.get(url) requests.get(url)的各种属性 print(response.text)print(…

Flink Watermark 源码分析

随着 flink 的快速发展与 API 的迭代导致新老版本差别巨大遂重拾 flink&#xff0c;在回顾到时间语义时对 watermark 有了不一样的理解。 一、如何生成 在 flink 1.12(第一次学习的版本)时 watermark 生成策略还有两种: punctuated 和 periodic&#xff0c;在 1.17 中 punctua…

基于自建靶场三层网络的内网渗透

注意&#xff1a;一切内容仅用于安全技术的分享&#xff0c;切勿用于其他用途&#xff0c;产生严重的后果与作者无关 前言介绍&#xff1a; 网络拓扑图&#xff1a; 为了方便起见&#xff0c;我在每个服务器放有webshell&#xff0c;这里主要是让我们熟悉sock代理的使用。 这…