深入理解STL库

article/2025/9/30 16:39:47

关注本人公众号,获取更多学习资料!

微信公众号搜索:阿Q正砖

上期说过C++这块面试问的东西也蛮多,简历上只要出现C++这几个字,那么STL库就是必问。

总不能是面试官问你了解STL库吗?你尴尬的说这块不怎么熟悉。那这就…

总的来说STL库这块也不是那么难理解,算了…说太多容易挨打,直接就进入正题吧。

STL库

一、基本概念

1、分类

标准序列容器:vector、string、deque和list。

标准关联容器:set、multiset、map和multimap。

非标准序列容器:slist和rope。slist是一个单向链表,rope本质上是一个“重型”string。

非标准关联容器:hash_set、hash_muliset、hash_map、hash_multimap。

2、六大组件

容器(Containers):各种数据结构,如Vector,List,Deque,Set,Map用来存放数据,STL容器是一种Class Template,就体积而言,这一部分很像冰山载海面的比率。

算法(Algorithms):各种常用算法如Sort,Search,Copy,Erase,从实现的角度来看,STL算法是一种Function Templates。

迭代器(Iterators):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有五种类型,以及其它衍生变化,从实现的角度来看,迭代器是一种将:Operators*,Operator->,Operator++,Operator–等相关操作予以重载的Class Template。所有STL容器都附带有自己专属的迭代器——是的,只有容器设计者才知道如何遍历自己的元素,原生指针(Native pointer)也是一种迭代器。

仿函数(Functors):行为类似函数,可作为算法的某种策略(Policy),从实现的角度来看,仿函数是一种重载了Operator()的Class 或 Class Template。一般函数指针可视为狭义的仿函数。

适配器(配接器)(Adapters):一种用来修饰容器(Containers)或仿函数(Functors)或迭代器(Iterators)接口的东西,例如:STL提供的Queue和Stack,虽然看似容器,其实只能算是一种容器配接器,因为 它们的底部完全借助Deque,所有操作有底层的Deque供应。改变Functor接口者,称为Function Adapter;改变Container接口者,称为Container Adapter;改变Iterator接口者,称为Iterator Adapter。配接器的实现技术很难一言蔽之,必须逐一分析。

分配器(Allocators):负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的Class Template。

3、迭代器

输入迭代器:是只读迭代器,在每个被遍历到的位置上只能被读取一次。

输出迭代器:是只写迭代器,在每个被遍历到的位置上只能被写入一次。

前向迭代器:兼具输入和输出迭代器的能力,但是它可以对同一个位置重复进行读和写。前向迭代器不支持operator–,所以它只能向前移动。所有的标准STL容器都支持比前向迭代器功能更强大的迭代器。

双向迭代器:很像前向迭代器,只是它们向后移动和向前移动同样容易。标准关联容器都提供了双向迭代器。list也是如此。

随机访问迭代器:有双向迭代器的所有功能,而且,它还提供了“迭代器算术”,即在一步内向前或向后跳跃的能力。vector、string和deque都提供了随机访问迭代器。指向数组内部的指针对于数组来说也是随机访问迭代器。

二、底层原理及相关面试题

1、Vector

vector底层是一个动态数组,内存是连续的,每次以原来空间大小的2倍来进行扩容的。

(1)容器中,对象的构造析构,内存的开辟释放,通过容器的空间配置器allocator来实现的。

(2)增删查

vector vec;

增加:

vec.push_back(); 末尾添加元素O(1),导致容器扩容。

vec.insert(it,20); 迭代器指向的位置添加一个元素20 O(n) 导致容器扩容。

删除:

vec.pop_back(); 末尾删除元素O(1)。

vec.erase(it); 删除it迭代器指向的元素O(n)。

查询:

operator[] 下标的随机访问vec[5] O(1)。

iterator迭代器进行遍历。

注意:对容器进行连续插入或者删除操作(insert/erase),一定要更新迭代器,否则第一次insert或者erase完成,迭代器就失效了。

(3)常用的函数

reserve(20):vector预留空间的,只给容器底层开辟指定大小的内存空间并不会添加新的元素。

resize(20):容器扩容用的,不仅给容器底层开辟指定大小的内存空间,还会添加新的元素。

swap:两个容器进行元素交换。

(4)reserve()和resize()的区别

reserve()是直接扩充到已经确定的大小,可以减少多次开辟、释放空间的问题,这样的话就可以提高效率,它还可以减少多次要拷贝数据的问题。reserve()只有一个参数。

resize()可以改变有效空间的大小,也有改变默认值的功能。capacity的大小也会随着改变。resize()可以有多个参数。

(5)size()和capacity()的区别

size表示当前vector中有多少个元素。

capacity表示它已经分配的内存中可以容纳多少元素。

(6)迭代器失效情况

当插入一个元素到vector中,由于引起了内存重新分配,所以指向原内存的迭代器全部失效。

当删除容器中一个元素后,待迭代器所指向的元素已经被删除,也会造成迭代器失效。erase()方法会返回下一个有效的迭代器,所以当我们要删除某个元素时,需要it=vec.erase(it);。

2、Deque

deque是一个双向开口的容器,所谓双向开口就是在头尾两端均可以做元素的插入和删除操作。(双端队列)

动态开辟的二维数组,第二维固定长度的数组空间,扩容的时候(第一维的数组进行2倍扩容)

(1)deque相比于vector最大的差异就在于支持常数时间内对首尾两端进行插入和删除操作,而且deque没有容量的概念,其内部采用分段连续内存空间来存储元素,在插入元素的时候随时都可以重新增加一段新的空间连接起来。

(2)deque提供了Ramdon Access Iterator,同时也支持随机访问和存取,但是它也为此付出了昂贵的代价,其复杂度不能跟vector的原生迭代器相提并论。

(3)deque的中控器

在这里插入图片描述

deque为了维持整体连续的假象,设计一个中控器,其用来记录deque内部每一段连续空间的地址。大体上可以理解为deque中的每一段连续空间分布在内存的不连续空间上,然后用一个所谓的map作为主控,记录每一段内存空间的入口,从而做到整体连续的假象。

(4)deque的迭代器

deque提供的是一个随机访问迭代器,由于是分段连续空间,其必须记录当前元素所在段的信息,从而在该段连续空间的边缘进行前进或者后退的时候能知道跳跃到的上一个或下一个缓冲区。deque必须完完整整的掌握和控制这些信息,以达到正确的跳跃。

buffer_size函数:

static size_t buffer_size(){
return __deque_buf_size(BufSiz, sizeof(T));
}
//如果n不为0,传回n,表示buffer size 由自己定义
如果n为0,表示buffer_size 采用默认值
如果sz(元素大小) < 512,传回512/sz,如果不小于512 ,传回1
inline size_t __deque_buf_size(size_t n, size_t sz)
{
return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
}

set_node函数:当迭代器处在当前缓冲区的边缘时,一旦前进或者后退,就要考虑超过当前缓冲区的情况,此时需要跳转到下一个缓冲区,这时候set_node就派上用场了。

void set_node(map_pointer new_node)
{node = new_node;      // 跳转到相应缓冲区first = *new_node;    // 更新跳转后缓冲区first信息last = first + difference_type(buffer_size());  // 更新跳转后缓冲区last的信息
}

(5)deque的数据结构

deque维护着一个map,用来记录每个缓冲区的位置。除了map外,deque的数据结构还维护着start和finish两个迭代器,分别指向deque的首尾。此外,他还必须知道map的大小,一旦map提供的节点不足,就需要配置一块更大的map。

3、List

list的底层是一个双向循环链表,以节点为单位存放数据,节点的地址在内存中不一定连续,每次插入或删除一个元素,就配置或释放一个元素空间。list不支持随机存取,适合需要大量的插入和删除,而不关心随机存取的应用场景。

(1)迭代器

因为list的底层结构为带头结点的双向循环链表,可将迭代器暂且理解为指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

(2)增删改查

增:

使用函数push_front(); 头插
使用函数push_back(); 尾插
使用函数insert(); 在position位置中插入值为val的元素

删:

使用函数pop_front(); 头删
使用函数pop_back(); 尾删
使用函数clear清空list中的有效函数

改:

利用迭代器对list元素进行修改
使用swap交换两个元素

查:

使用find函数查找,这是算法模块实现,不是list的成员接口

(3)list的优缺点

优点:

list的头部、中间插入不需要挪动数据,效率较高,均为O(1)。

list插入数据是新增节点,不需要扩容,因此节省了空间。

缺点:

不支持随机访问,[]操作符和list.at();

底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低。

(4)常用函数

list.push_back();     //在尾部插入一个数据
list.pop_back();      //删除尾部数据
list.push_front();    //在头部插入一个数据
list.size();          //返回容器中实际数据的个数
list.sort();          //排序,默认由小到大
list.erase();         //删除一个元素,参数是迭代器,返回的是删除迭代器的下一个位置

4、Map || Multimap || Set || Multiset

底层原理都是红黑树。

Map 类似于数据库中1:1关系,是一种关联容器,提供一对一的数据处理能力,这种特性使得map类似于数据结构中红黑树。元素默认按键的升序排序。如果迭代器所指向的元素被删除,则该迭代器失效。其它任何增减、删除元素的操作都不会使迭代器失效。所有元素都会根据元素的键值自动被排序。map的所有元素都是pair,同时拥有实值value和键值key。pair的第一个元素被视为键值,第二个元素被视为实值。map不允许俩各元素拥有相同的键值,由于红黑树是一种平衡二叉搜索树,自动排序的效果很不错,所以标准库STLmap都是以红黑树为层级制。又由于map所开放的各种操作接口,红黑树也都提供了,所以几乎所有map的操作行为,都是红黑树的操作行为。

Multimap类似于数据库中1:N关系,是一种关联容器,提供一对多的数据处理能力。

Set类似于数学里的集合,但是set的集合不包含重复的元素。按照键进行排序存储,值必须可以进行比较,可以理解为set就是键和值相等的map。如果迭代器所指向的元素被删除,则该迭代器失效。其它任何增加、删除元素的操作都不会使迭代器失效。

Multiset类似于数学里的集合,multiset的集合包含重复的元素。

5、unordered_map || unordered_set || unordered_multimap || unordered_multiset

unordered_map和unordered_multimap是无序排列的,其底层实现为hash table。hash table最大的优点就是把数据的存储和查找消耗的时间大大降低,时间复杂度为O(1),代价仅仅是消耗比较多的内存。

unordered_set和unordered_multiset底层实现是hash table。

总结:

在这里插入图片描述

强烈建议收藏,面试一定会用得到!!!


http://chatgpt.dhexx.cn/article/RGw29mun.shtml

相关文章

C++ STL标准库

STL 组件 STL 是 C 标准程序库的核心。STL 内的所有组件都由模板构成&#xff0c;其元素可以是任意型别。程序员通过选用恰当的群集类别调用其成员函数和算法中的数据即可&#xff0c;但代价是 STL 晦涩难懂。 STL 组件主要包括容器&#xff0c;迭代器、算法和仿函数。 容器…

C++语法篇之STL库

1. STL介绍 STL是Standard Template Library的缩写&#xff0c;即标准模板库。之前在写 Templates 模板的时候&#xff0c;提到过STL对于模板的应用。STL是由多个模板类构成&#xff0c;能够为开发者提供通用的数据结构和算法。 STL主要包含以下内容&#xff1a; 容器 Conta…

【c++ • STL】初步认识什么是 STL 标准库

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;从零开始的 c 之旅&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&#xff0c;不行的…

STL库:list

STL库&#xff1a;list 文章目录 STL库&#xff1a;list1.STL库对list的官方介绍2.list的常用接口2.1 list的构造函数2.2 list的迭代器与遍历操作2.3 list的容量操作2.4 list的访问操作2.5 list的修改操作2.6 list的特别容器操作 3.list的底层源码4.list的模拟实现4.1 list的结…

STL库:string

STL库&#xff1a;string 文章目录 STL库&#xff1a;string1.STL库对于string类的介绍2.string常用接口的掌握2.1 string的构造接口2.2 string的容量操作接口2.3 string的访问操作接口2.4 string的迭代器遍历操作接口2.5 string的修改操作接口2.6 string的非成员函数重载接口2…

C++ 标准模板库STL

目录 前言 一、STL简介 二、STL的组件 三、STL头文件与命名空间 四、STL三大组件之 —— 容器 4.1 容器概述 4.2 序列式容器 4.3 排序式容器 4.4 哈希容器 五、STL三大组件之 —— 迭代器 5.1 迭代器概述 5.2 五种迭代器 5.3 迭代器的定义 5.4 迭…

C++ - STL标准库

1.C STL标准库简介 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西&#xff0c;以及一种得以制造出”可重复运用的东西” 的方法&#xff0c;从函数(functions)&#xff0c;类别(classes),函数库(function libraries),类别库(class libraries)、各种 组件&…

STL库--概述

C标准模板库&#xff08;Standard Template Library,STL&#xff09;是泛型程序设计最成功的实例。STL是一些常用数据结构和算法的模板的集合。 STL六大组件&#xff1a; 容器&#xff08;containers&#xff09;&#xff1a;存放数据 算法&#xff08;algorithms&#xff09;&…

Standard Template Library(STL,标准模板库)

Standard Template Library(STL&#xff0c;标准模板库) STL&#xff08;标准模板库&#xff09;是C标准程序库的核心&#xff0c;它深刻影响了标准程序库的整体结构。 STL是一个泛型(generic)程序库&#xff0c;提供一系列软件方案&#xff0c;利用先进&#xff0c;高效的算…

pyqt学习笔记

pyqt学习笔记 文章目录 pyqt学习笔记前言pyqt主要模块开发环境安装qtpython选择使用anaconda集成版本&#xff1a;anaconda的特点&#xff1a;安装步骤&#xff1a; pycharm导入anaconda:pycharm设置qtdesigner&#xff0c;ui转py工具: 前言 gui学习是一个比较重要的内容&…

[ PyQt入门教程 ] PyQt5开发环境搭建和配置

PyQt5工具可以快速实现简单的界面开发&#xff0c;包括界面设计、布局管理以及业务逻辑实现&#xff08;信号与槽&#xff09;。简单说就是使用PyQt5工具可以快速画一个控件摆放整齐、界面整洁有序、布局合理的界面。 课程目标 可以动手实现简单的GUI程序。系列文章主要以动手…

PyQt(QtDesigner+Python)编写程序的使用教程(简单版)

有同学问我具体怎么实现QtDesignerPython&#xff0c;简单写一下方便查看 1.安装好后Qtdesinger,打开软件&#xff0c;操作控件设计好想要的界面&#xff1b; 2.将Qtdesinger编写的.ui文件&#xff0c;使用PyUIC&#xff08;需要自己安装配置好&#xff09;软件转到.py文件 …

Python开发:PyQT安装教程

不管开发什么程序&#xff0c;一个友好的用户界面都是至关重要的&#xff0c;然而Python自身并没有集成GUI&#xff0c;但是好在自Python诞生之日起&#xff0c;就有许多优秀的GUI工具集被整合到Python当中&#xff0c;使得Python也可以在图形界面编程领域大展身手。所以从这一…

PyQt5学习教程

介绍 Qt&#xff08;官方发音 [kju:t]&#xff0c;音同 cute&#xff09;是一个跨平台的 C 开发库&#xff0c;主要用来开发图形用户界面&#xff08;Graphical User Interface&#xff0c;GUI&#xff09;程序&#xff0c;当然也可以开发不带界面的命令行&#xff08;Command…

PyQt完整入门教程 | 例程附代码

关注、星标公众号&#xff0c;直达精彩内容 来源&#xff1a;cnblogs 作者&#xff1a;lovesoo 1、GUI开发框架简介 pyqt是个好东西&#xff0c;可以做完整的测试方案、脚本、工具进行整合复用等等&#xff0c;本文将以一个实例和大家一起分享。先给自己挖个坑开个头&#xff0…

PyQt初级教程

PyQt5简介 这是一个PyQt5的入门教程.目的是帮助你使用PyQt5.本教程创建并在Linux上测试.PyQt4教程则覆盖了PyQt4,对应Python的2.x和3.x的Qt4的库. 原作地址&#xff1a;http://zetcode.com/gui/pyqt5/ 原翻译地址 &#xff1a;http://blog.csdn.net/neverstop_2009/article/c…

PyQt4入门教程(2)_PyQt4的第一个程序

注&#xff1a;文中译者的话将用方括号【】标出。 这一部分我们将学习PyQt中一些基本的函数。 一个简单的例子 这是一个能够显示出一个窗口的简单例子。目前为止我们已经可以对这个窗口干很多事情了&#xff0c;比如说改变它的尺寸&#xff0c;最大化&#xff0c;最小化………

一、PyQt基础知识

一、基础知识 &#xff08;一&#xff09;简介 1. 什么是PyQt5 PyQt是基于Digia公司强大的图形程序框架Qt的Python接口&#xff0c;由一组Python模块构成&#xff0c;它是一个创建GUI应用程序的工具包&#xff0c;由Phil Thompson开发。 自从1998年首次将Qt移植到Python上形…

PyQt完整入门教程

https://blog.csdn.net/baidu_37503452?spm1000.2115.3001.5343 1、GUI开发框架简介 19年来&#xff0c;一直在做Android ROM相关测试&#xff0c;也有了一定的积累&#xff1b;20年&#xff0c;计划把之前完整的测试方案、脚本、工具进行整合复用。 第一期计划是开发一个GUI的…

PyQt上手教程汇总

根据此前的PyQt学习&#xff0c;这里对PyQt的学习过程进行最后的总结 前文链接&#xff1a;由于前文标题名字取了一样的,以下内容按照前后顺序排列 (1)PyQt上手教程&#xff08;一&#xff09;_机械刘怀洋的博客-CSDN博客 (2)PyQt上手教程&#xff08;一&#xff09;_机械刘…