STL容器(持续更新中)

2023-10-27

一、string类

1. 构造函数

常用的构造函数如下。

构造函数原型 含义
string() 默认构造函数。创建一个默认string对象,长度为0
string(const string &s) 拷贝构造函数。用一个string对象初始化另一个string对象
string(const char *s) 用字符串常量构建string对象
string(size_n n, ch ar c) 构造一个包含n个元素的string对象,其中每个字符都被初始化为字符c

字符串常量,也就是C-风格的字符串,例如char str[] = "hello"
string类虽然看起来使用方法与C中的字符串数组差不多,但它并不是基于char类型实现的,而是基于模板类basic_string<char>的一个typedef。

#include <string>
string str;
string str1("hello world");
string str2(str1);
string str3(3, 'a');	// string对象为3个字符'a'

2. 运算符重载

string类中重载了一些运算符,使字符串操作更方便。

重载运算符 含义
>> cin字符串输入
<< cout字符串输出
= 将一个字符串赋给另一个字符串,可以附加字符串常量、单个char字符或string对象
+ 将两个字符串连在一起,操作对象可以是字符串常量、单个char字符或string对象
+= 将一个字符串附加到另一个字符串后面,可以附加字符串常量、单个char字符或string对象
[] 访问字符串中的各个字符
> >= < <= == != 比较字符串的大小,比较对象可以是string类或字符串常量

3. 常见成员函数

#include <string>
string str;

1. 获取字符串的长度
int len1 = str.length()
int len2 = str.size()
length()来自较早的string类,size()成员为STL兼容性添加的

2. 在字符串中搜索指定的字符或子字符串
函数原型:size_type find(const string & str, size_type pos = 0)const
从字符串的迫使、位置开始,查找字符串str
如果找到,则返回该子字符串首次出现时首个字符的索引;否则,返回string::npos
第一个参数也可以是char型(单个字符)或const char *型(字符串常量)

3. 容量操作
返回分配给字符串的内存块的大小:int cap = str.capacity()
规定请求内存块的最小长度:str.reserve(10)

4. 类型转换
将string字符串转换成c风格的字符串常量:const char *s = str.c_str()

npos是string类的静态成员,它的值是string对象能存储的最大字符数。由于索引从0开始,所以它比最大的索引值大1,因此可以使用它来表示没有查找到字符或字符串。

字符串在内存中占用一段连续的地址空间。如果进行将一个字符串连接到另一个字符串末尾的操作,则占用的空间变大,但相邻的内存可能已经被占用了,因此,需要分配一块新的连续内存块给连接后的字符串,字符串的内容复制到新的内存单元中。如果大量执行这样的操作,效率将非常低。因此,很多C++实现分配一个比实际字符串大的内存块,满足扩充字符串长度的需求。如果字符串长度依旧超出原有的范围,则程序将分配一个大小为原来两倍的新内存块,以提供足够大的空间。

举个例子

string small = "bit";
cout << small.capacity() << endl; // 输出15
small.reserve(50);
cout << small.capacity() << endl; // 输出63

二、标准库模板

1. 迭代器

所谓的迭代器,是一个广义指针。迭代器能够为STL的各种不同的容器类提供统一处理的接口,这些类通常都是简单指针无法处理的。每个容器类都定义了一个合适的迭代器,该迭代器的类型是一个名为iterator的typedef,其作用域为整个类。例如,声明一个double类型的vector容器的代码如下。

vector<double>::iterator pd;

2. STL通用方法

指向T的迭代器类型:X::iterator
T的类型:X::value_type
返回容器中元素的个数:a.size()
交换a和b的内容:a.swap(b)
清空容器中的元素,但不释放空间:a.clear()
返回指向容器中第一个元素的迭代器:a.begin()
返回指向容器超过容器尾的迭代器:a.end()
比较a和b,需要满足a和b长度相同,且每个元素都相等:a == b
比较a和b,不相等情况:a != b

3. vector矢量

传统的数组array是一块连续、固定的空间,并不能自由地改变array的大小,也就难以在数组中插入、删除元素。为了解决这个问题,C++定义了vector容器。

vector所采用的数据结构是线性连续空间,但是允许动态改变空间地大小。如果要换大一点或者小一点的空间,首先配置一块新的空间,然后将旧空间的数据拷贝到新空间,再释放原来的空间。

为了降低空间配置时的速度成本,vector实际配置的大小可能比用户实际需求大一些,以备将来可能的扩充,这边是容量(capacity)的概念。换句话说,一个vector的容量永远大于或等于其大小,一旦容量等于大小,便是满载,如果再有新增元素,整个vector容器就要在内存中再寻找一块满足容量大小地新居所,并将所有数据拷贝过去。

动态增加大小并不是在原空间之后续直接接新空间,因为无法保证原空间之后的空间没有被其他数据占用。因此找更大的内存空间,然后将原数据拷贝新空间,释放原空间。通常会新分配的空间是原空间大小的两倍。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。

因为vector维护的是一个连续空间,因此支持随机存取,提供随机访问迭代器(Random Access Iterators)。vector迭代器的功能可以完全覆盖普通指针的各种操作,如operator*, operator->, operator++, operator–, operator+, operator-, operator+=, operator-=,这些运算符的使用方式与普通指针完全相同。

创建vector类对象。

#include <vector>
创建vector对象,一维
不指定大小:vector<int> vec;
指定大小为5:vector<int> vec(5);

创建vector对象,二维
不指定大小:vector<vector<int>> vec;
指定大小,55列:
vector<int> temp(5);
vector<vector<int>> vec(5, temp));

vector类的操作。

#include <vector>
vector<int> vec;

容量操作:
获取数据个数:int size = vec.size()
获取容量大小:int cap = vec.capacity()
判断是否为空:vec.empty()
改变vector的size:vec.resize()
改变vector的capacity:vec.reserve()

增删查改:
int a;
int pos;
尾插:vec.push_back(a)
尾删:a = vec.pop_back()
查找:find
在pos之前插入元素a:vec.insert(pos, a);
删除pos位置的元素:vec.erase(pos);

vector的非成员函数。

对容器中的某一段元素进行遍历:for_each(起始位置,结束位置,函数指针)
例如
vector<Review>::iterator pr;
for (pr = books.begin(); pr != books.end(); pr++)
	ShowReview(*pr);
改写成for_each函数为
for_each(books.begin(), books.end(), ShowReview);

随机排列指定区间内的元素:Random_shuffle(起始位置,结束位置)
例如Random_shuffle(books.begin(), books.end());

对指定区间内的元素进行排序:sort(起始位置,结束位置)
如果容器元素是用户自定义的对象,则必须对运算符<进行重定义operator<()

4. deque双端队列

vector容器是单向开口的连续内存空间,允许在尾部插入新元素,尽管vector容器也可以在头部或中间插入元素,但效率极低,因为需要挨个向后面挪动元素。

deque容器则是一种双向开口的连续线性空间,头尾两端都可以做元素插入和删除操作。deque容器在逻辑空间上看是连续的,但实际上物理空间并不连续。每段数据空间内部是连续的,而每段数据空间之间则不一定连续。

deque由若干段的缓冲区构成,缓冲区中存放真实数据,同时使用一个中控器,维护每段缓冲区的地址。中控器是一种map(注意,不是STL的map容器),是一小块连续空间,其中每个元素(此处称为一个节点,node)都是指针,指向另一段(较大的)连续线性空间,称为缓冲区。缓冲区才是deque的储存空间主体。如下图所示。
deque的物理结构
deque除了维护一个指向map的指针外,还维护start、finish两个迭代器,分别指向第一缓冲区的第一个元素和最后缓冲区的最后一个元素(的下一位置)。此外,也必须记住目前的map大小,因为一旦map的所提供的空间不足,它将需要重新配置一个更大的空间,依然是经过三个步骤:配置更大的、拷贝原来的、释放原空间。

deque容器和vector容器的差异:

  1. deque能够在在常数项时间内在头部进行插入和删除操作,vector头插需要挨个挪动后面的元素。
  2. 在于deque没有容量的概念,因为它以分段的连续空间组合而成,随时可以增加一段新的空间并链接起来。deque不需要像vector那样预留一部分空间来减少重新分配内存并拷贝数据的次数。
  3. deque容器也提供了随机访问迭代器,但是它的迭代器并不是普通的指针,因此也比vector的迭代器实现起来更复杂。因此,除非有必要,我们应该尽可能的使用vector,而不是deque。

deque的常用操作函数如下。

#include <deque>
deque<int> elem;

两端插入删除:
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器的第一个数据

指定位置操作:
insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
clear();//清空容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);//删除pos位置的数据,返回下一个数据的位置

5. stack栈

栈是一种先进后出的数据结构,stack容器的底层实现是deque,stack没有迭代器。

#include <stack>
stack<int> st;
int a;
把元素a入栈:st.push(a)
栈顶元素出栈(没有返回值):st.pop()
返回栈顶元素(栈顶元素不出栈):a = st.top()
判断栈是否为空(为空则返回true):st.empty()

6. queue队列

队列是一种先进先出的数据结构,queue容器的底层实现是deque,queue没有迭代器。

#include <queue>
queue<int> q;
int a;
在队尾添加a元素:q.push(a)
移除队头元素(没有返回值):q.pop()
返回队头元素(队头元素不出队):a = q.front()
返回队尾元素(队尾元素不出队):a = q.back()
判断队列是否为空(为空则返回true):q.empty()

7. list双向循环链表

list的数据结构是双向循环链表,在逻辑空间上是连续的,但在物理空间上是非连续、非顺序的。它可以在常数时间内完成元素的插入和删除,但不支持随机访问,

list容器的迭代器是一种双向迭代器(Bidirectional Iterator),有能力进行正确的递增、递减、取值、成员存取操作:递增时指向下一个节点,递减时指向上一个节点,取值时取的是节点的数据值,成员取用时取的是节点的成员。

list的元素插入操作和删除操作都不会造成原有list迭代器的失效。这在vector是不成立的,因为vector的插入操作可能造成记忆体重新配置,导致原有的迭代器全部失效,但list不会。

list的常用操作函数如下。

#include <list>
list<int> l;
int a;
在链表头添加a元素:l.push_front(a)
从链表头移除元素(没有返回值):l.pop_front()
在链表尾添加a元素:l.push_back(a)
从链表尾移除元素(没有返回值):l.pop_back()

insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
clear();//清空容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);//删除pos位置的数据,返回下一个数据的位置
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STL容器(持续更新中) 的相关文章

随机推荐

  • Vue应用方法、实例属性、实例方法$refs、vm.$nextTick等

    应用方法 实例属性 实例方法 Vue 中对部分特殊的属性和功能方法进行特殊指代定义 用于提供独立的执行和 获取方式 应用方法 mount 所提供 DOM 元素的 innerHTML 将被替换为应用根组件的模板渲 染结果 unmount 卸载
  • java prepare_java中prepareStatement与createStatement的区别

    首先来看两段代码 第一个使用createStatement 1 public void delete intid 2 try 3 Connection c DBUtil getConnection 4 Statement s c creat
  • Nginx之location匹配规则

    什么是location nginx就是通过拦截到的请求去对配置好的location块 location block 进行请求代理的 被代理的URL去对location后边的字符串 或正则 根据一定的规则进行匹配 然后执行对应location
  • 你是否曾质疑过DB-Engine的数据库排名?

    在谈论数据库的最新趋势时 我们习惯了参考DB Engine上所提供的排名信息 每当新的报告出来时 我们也时常看到各个媒体网站争先发布关于最新排名的分析内容 如标题所言 你是否曾质疑过DB Engine所给出的这份排名 如下是2018年3月份
  • php后台接收blob文件流,php – 我们如何访问服务器中的文件blob?

    在上传大于maxChunkSize的文件时 我们如何在服务器中单独访问每个上传的文件blob 我的问题是我需要使用后端api将上传的文件在单独的blob中转发到不同的服务器 到目前为止 看看wiki 对于1 mb的块 我在js中添加了以下内
  • Python logging将日志输出到Kafka

    Python logging用于输出Python程序运行的日志 现实中往往一个项目会部署在多台机器之上 这种情况下 为了方便对各主机运行日志进行收集 往往会使用消息队列 通过消息队列将各台机器上的日志收集并写入日志文件 本文使用Python
  • linux库概念及其编程

    分文件编程案例 好处 分文件编程思想 功能责任划分 方便调试 主程序简洁 例子 demo c include
  • 在外包做了3年,离职后成功入职字节跳动....

    最近换了份工作 当时和群里的朋友也聊过换工作的话题 他们都觉得这是一次非常冒险的行为 说我这是一次豪赌 成了会有更好的职业发展 没成可能就会出现两三年的发展断层 甚至影响职业生涯路径 一步错 步步错 我当时也仔细的考虑过了 的确有很大的风险
  • STM32标准IIC驱动

    IIC Inter Integrated Circuit 总线是一种由 PHILIPS 公司开发的两线式串行总线 用于连接 微控制器及其外围设备 也是目前很流行的通讯总线 使用IIC总线做产品能够很大程度上降低PCB的布线难度 以及布线数量
  • fio使用good blog

    Linux应用 磁盘IO读写测试工具 FIO详解 协议森林的博客 CSDN博客 fio读写测试 编译安装 常用参数 实例 结果说明 SSD测试第一神器 FIO 磁盘IO体系架构与存储解决方案 pudn com 磁盘性能指标 IOPS与吞吐量
  • DC-5靶场(一般详细)

    目录 简介 一 找IP地址 二 扫描IP端口 三 找web漏洞 文件包含 四 拿webshell 五 提权 总结 简介 dc系列靶场是比较适合新手的黑盒测试靶场 其中dc 5靶场下载连接如下 dc 5靶场下载地址 一 找IP地址 netdi
  • 蓝桥杯2013c++真题:振兴中华

    思路一 dfs暴力搜索 从我做起振兴中华分别为12345678 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 迷宫问题模板 dfs x y path 从 x y 深度优先搜索 if x y为终点坐标 x y
  • 静态库的生成与使用

    1 静态库的生成与使用 1 我自己写一个 c 文件 里面存放我定义的函数 1 include
  • 酷炫网页按钮,炫酷变色效果(附源码)

    酷炫网页按钮 效果如下图 目录如下 html代码如下 index html a href sunbtton a css代码 inedex css margin 0px padding 0px body
  • 【C++】封装map和set(红黑树实现)

    前言 前面 我们学习了set和map的用法 这两个容器可以完成查找 排序等操作 后来我们在学习过二叉搜索树的基础上又学习了两种特殊的二叉搜索树 AVL树和红黑树 他们俩可以是效率进一步提高 其实set和map的底层就是由红黑树封装而成的 所
  • Camunda 入门开发指南 - 1 初始化spring boot项目

    目录 Camunda Platform Initializr 代码结构 Application spring boot启动类 Camunda在spring中的配置 Camunda流程定义文件 Camunda Modeler 工作流定义 图形
  • 面试总结 - 计算机网络

    计算机网络 1 OSI 七层模型 TCP与UDP 响应状态码 OSI 模型 应用层 计算机用户 以及各种应用程序和网络之间的接口 其功能是直接向用户提供服务 完成用户希望在网络上完成的各种工作 HTTP SMTP FTP DNS 表示层 负
  • permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

    错误 permission denied while trying to connect to the Docker daemon socket at unix var run docker sock Get http 2Fvar 2Fru
  • 基于springboot开发项目架构之Eureka

    Eureka介绍 Spring Cloud Eureka 是对Netflix公司的Eureka的二次封装 它实现了服务治理的功能 Spring Cloud Eureka提供服务端与客户端 服务端即是Eureka服务注册中心 客户端完成微服务
  • STL容器(持续更新中)

    一 string类 1 构造函数 常用的构造函数如下 构造函数原型 含义 string 默认构造函数 创建一个默认string对象 长度为0 string const string s 拷贝构造函数 用一个string对象初始化另一个str