C++ STL

本文详细介绍了STL的六大组件(容器、算法、迭代器、仿函数、适配器和空间配置器),以及它们的交互关系。重点探讨了STL的高可重用性、高性能和模块化设计,包括vector、list、deque等常见容器的特点和适配器如queue和stack的实现。
摘要由CSDN通过智能技术生成

什么是STL

六大组件

容器(Container)

各种数据结构,如vector、list、deque、set、map等,⽤来存放数据,从实现⻆度来看,STL容器是⼀种class template。

算法(Algorithm)

各种常⽤的算法,如sort、find、copy、for_each。从实现的⻆度来看,STL算法是⼀种function template。

迭代器(Iterator)

扮演了容器与算法之间的胶合剂,共有五种类型,从实现⻆度来看,迭代器是⼀种将operator* , operator-> , operator++,operator–等指针相关操作予以重载的class template。

仿函数(Function object)

⾏为类似函数,可作为算法的某种策略。从实现⻆度来看,仿函数是⼀种重载了operator()的class 或者class template。

适配器(Adaptor)

⼀种⽤来修饰容器或者仿函数或迭代器接⼝的东⻄。

STL提供的queue 和 stack,虽然看似容器,但其实只能算是⼀种容器配接器,因为它们的底部完全借助deque, 所有操作都由底层的deque供应。

空间配置器(Allocator)

负责空间的配置与管理。从实现⻆度看,配置器是⼀个实现了动态空间配置、空间管理、空间释放的class template。

六大组件的交互关系

容器通过空间配置器取得数据存储空间

算法通过迭代器存储容器中的内容

仿函数可以协助算法完成不同的策略的变化

适配器可以修饰仿函数



STL优点

高可重用性

STL 中⼏乎所有的代码都采⽤了模板类和模版函数的⽅式实现,这相⽐于传统的由函数和类组成的库来说提供了更好的代码重⽤机会。

高性能

高移植性

将数据和操作分离

数据由容器管理,操作由算法定义。迭代器在两者之间充当“粘合剂”,以使算法可以和容器交互运作。





容器

常见的容器

序列容器

vector
list
deque
array
forward_list

关联容器

set
mutiset

map
mutimap

unordered_set
unordered_mutiset

unordered_map
unordered_mutimap

带muti的是多重集合,允许重复;

带unordered的是无序集合;

带set是普通集合,带map是键值对集合;

set,map,unordered_set,unordered_map支持快速查找、插入和删除

适配器容器

stack:是⼀个基于底层容器的栈实现,默认使用deque

queue:是⼀个基于底层容器的队列实现,默认使用deque

priority_queue:是⼀个基于底层容器的优先队列实现,默认使用vector



vector容器

底层实现

vector在中分配了一段连续的内存空间来存放元素

三个迭代器

first:指向vector中对象的起始字节位置

last:指向当前最后一个元素的末尾字节

end:指向整个vector容器所占用空间的末尾字节
在这里插入图片描述

扩容过程

固定扩容

机制:每次扩容的时候在原 capacity 的基础上加上固定的容量

优点:固定扩容⽅式空间利⽤率⽐较⾼。

缺点:考虑⼀种极端的情况,vector每次添加的元素数量刚好等于每次扩容固定增加的容量 + 1,就会造成⼀种情况,每添加⼀次元素就需要扩容⼀次,⽽扩容的时间花费⼗分⾼昂。所以固定扩容可能会⾯临多次扩容的情况,时间复杂度较⾼。

成倍扩容

机制:

每次扩容的时候原 capacity 翻倍

优点:⼀次扩容 capacity 翻倍的⽅式使得正常情况下添加元素需要扩容的次数⼤⼤减少(预留空间较多),时间复杂度较低;

缺点:因为每次扩容空间翻倍,⽽很多空间没有利⽤上,空间利⽤率不如固定扩容。



list容器

每个元素都是放在⼀块内存中,他的内存空间可以是不连续的,通过指针来进⾏数据的访问
list是⼀个环状的双向链表,同时它也满⾜STL对于“前闭后开”的原则,即在链表尾端可以加上空⽩节点



deque容器

双向队列,全称为double-ended queue,C++中deque是stack和queue默认的底层实现容器

deque是⼀个双端开⼝的连续线性空间,其内部为分段连续的空间组成,随时可以增加⼀段新的空间并链接

deque采⽤⼀块map作为主控,其中的每个元素都是指针,指向另⼀⽚连续线性空间,称之为缓存区,这个区才是
⽤来储存数据的,如下图所示。
deque结构图



容器间的区别

vector和list的区别

  1. 底层实现
    vector使用动态数组实现,list使用双向链表
  2. 随机访问
    vector是顺序内存,⽀持随机访问,list不⾏
  3. 内存扩容
    vector⼀次性分配好内存,不够时才进⾏翻倍扩容;list每次插⼊新节点都会进⾏内存申请
  4. 性能
    vector随机访问性能好,插⼊删除性能差;list随机访问性能差,插⼊删除性能好


map和set的区别

相同
都是C++的关联容器,只是通过它提供的接⼝对⾥⾯的元素进⾏访问,底层都是采⽤红⿊树实现。

不同
set:⽤来判断某⼀个元素是不是在⼀个组⾥⾯。
map:映射,相当于字典,把⼀个值映射成另⼀个值,可以创建字典。


map和unordered_map的区别

区别

map底层是基于红⿊树实现的,因此map内部元素排列是有序的。
⽽unordered_map底层则是基于哈希表实现的,因此其元素的排列顺序是杂乱⽆序的。

map优缺点

优点
有序性,这是map结构最⼤的优点,其元素的有序性在很多应⽤中都会简化很多的操作。
查找、删除、增加等⼀系列操作时间复杂度稳定,都为O(logn )。

缺点
查找、删除、增加等操作平均时间复杂度较慢,与n相关。

unordered_map优缺点

优点
查找、删除、添加的速度快,时间复杂度为常数级O(1)。

缺点
查找、删除、添加的时间复杂度不稳定,取决于哈希函数。极端情况下可能为O(n)。





适配器

stack和queue

栈与队列被称之为duque的配接器,其底层是以deque为底部架构。通过deque执⾏具体操作

heap和priority_queue

heap(堆)

建⽴在完全⼆叉树上,分为两种,⼤根堆,⼩根堆,其在STL中做priority_queue的助⼿,即,以任何顺序将元素推⼊容器中,然后取出时⼀定是从优先权最⾼的元素开始取,完全⼆叉树具有这样的性质,适合做priority_queue的底层

priority_queue(优先队列)

也是配接器。其内的元素不是按照被推⼊的顺序排列,⽽是⾃动取元素的权值排列,确省情况下利⽤⼀个max-heap完成,后者是以vector—表现的完全⼆叉树。





迭代器

左闭右开

在STL迭代器中,一般采用[ …. )的表示方法,也就是(iter1,iter2)中iter2表示的是最后一个元素后面的一个元素。这样做的好处在于循环时更干净利落。

迭代器有什么作⽤?什么时候迭代器会失效

作用

迭代器为不同类型的容器提供了统⼀的访问接⼝, 隐藏了底层容器的具体实现细节, 允许开发者使⽤⼀致的语法来操作不同类型的容器。

什么时候会失效

对于序列容器vector,deque来说,使⽤erase后,后边的每个元素的迭代器都会失效,后边每个元素都往前
移动⼀位,但是erase返回下⼀个有效的迭代器。

对于关联容器map,set来说,使⽤了erase后,当前元素的迭代器失效,但是其结构是红⿊树,删除当前元
素,不会影响下⼀个元素的迭代器,所以在调⽤erase之前,记录下⼀个元素的迭代器即可。

对于list来说,它使⽤了不连续分配的内存,并且它的erase⽅法也会返回下⼀个有效的迭代器,因此上⾯两种
⽅法都可以使⽤。





push_back 和 emplace_back 的区别

push_back ⽤于在容器的尾部添加⼀个元素。

container.push_back(value);

container 是⼀个⽀持 push_back 操作的容器,例如 std::vectorstd::list 等,⽽ value 是要添加的元素的值。

emplace_back ⽤于在容器的尾部直接构造⼀个元素。

container.emplace_back(args);

其中 container 是⼀个⽀持 emplace_back 操作的容器,⽽ args 是传递给元素类型的构造函数的参数。与 push_back 不同的是,emplace_back 不需要创建临时对象,⽽是直接在容器中构造新的元素

区别:
push_back 接受⼀个已存在的对象或⼀个可转换为容器元素类型的对象,并将其复制或移动到容器中。emplace_back 直接在容器中构造元素,不需要创建临时对象。

emplace_back 通常⽐ push_back 更⾼效,因为它避免了创建和销毁临时对象的开销。

emplace_back 的参数是传递给元素类型的构造函数的参数,⽽ push_back 直接接受⼀个元素。





  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值