【C++ STL】简述

  • C++ 的 STL( 全称是 Standard Template Library 标准模板库,也叫 泛型库)是一套功能强大的 C++ 模板类,提供了 通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈。
  • STL的分类
    • 标准函数库: 这个库是由通用的、独立的、不属于任何类的函数组成的。这个函数库继承自 C 语言,C++ 标准库包含了所有的 C 标准库,为了支持类型安全,做了一定的添加和修改。
      • 输入/输出 I/O
      • 字符串和字符处理
      • 数学
      • 时间、日期和本地化
      • 动态分配
      • 其他
      • 宽字符函数
    • 面向对象类库: 这个库是类及其相关函数的集合。标准的 C++ 面向对象类库定义了大量支持一些常见操作的类,比如输入/输出 I/O、字符串处理、数值处理。面向对象类库包含以下内容:
      • 标准的 C++ I/O 类
      • String 类
      • 数值类
      • STL 容器类
      • STL 算法
      • STL 函数对象
      • STL 迭代器
      • STL 分配器
      • 本地化库
      • 异常处理类
      • 杂项支持库
  • C++ 标准模板库包括以下 6 个组件(核心是前三个组件),每个组件都带有丰富的预定义函数,帮助我们通过简单的方式处理复杂的任务:
组件描述
容器
(Containers)
容器是用来 管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 list链表、stack栈、queue队列、vector向量、deque双向队列 等。
迭代器
(iterators)
迭代器用于 遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。
算法
(Algorithms)
算法作用于容器,它们提供了 各种通用算法 。包括对容器内容执行初始化、排序、搜索和转换等操作。
仿函数
(Functor)
如果一个类将 () 运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象(又称仿函数)
适配器
(Adaptor)
可以使一个类的接口(模板的参数)适配成用户指定的形式,从而让原本不能在一起工作的两个类工作在一起。值得一提的是,容器、迭代器和函数都有适配器;
分配器
(allocator)
为容器类模板提供自定义的内存申请和释放功能,由于往往只有高级用户才有改变内存分配策略的需求,因此内存分配器对于一般用户来说,并不常用。

【 1. 容器 】

  • 容器就是一些模板类的集合,但和普通模板类不同的是, 容器中封装的是组织数据的方法(也就是数据结构)
  • 序列式容器
    包括 array、vector、list、deque 和 forward_list,其存储的都是 C++ 基本数据类型(诸如 int、double、float、string 等)或使用结构体自定义类型的元素。
  • 关联式容器
    关联式容器在存储元素值的同时,还会 为各元素额外再配备一个值,又称为 ,其本质也是一个 C++ 基础数据类型或自定义类型的元素。它的功能是在使用关联式容器的过程中,如果 已知目标元素的键的值,则直接通过该键就可以找到目标元素,而无需再通过遍历整个容器的方式。
  • STL 容器种类和功能
    排序容器和哈希容器有时也称为 关联容器
容器种类功能举例
序列容器序列容器 中的 元素在容器中的位置同元素的值无关,即容器不是排序的。将元素插入容器时,指定在什么位置,元素就会位于什么位置。vector 向量容器
list 列表容器
deque 双端队列容器
排序容器
(有序关联式容器)
排序容器 中的 元素默认是由小到大排序好的,即便是插入元素,元素也会插入到适当位置。所以关联容器在查找时具有非常好的性能。set 集合容器
multiset多重集合容器
map映射容器
multimap 多重映射容器
哈希容器
(无序关联式容器)
哈希容器 中的 元素是未排序的,元素的位置由哈希函数确定C++ 11 新加入 4 种无序关联式容器,分别是:
unordered_set 哈希集合
unordered_multiset 哈希多重集合
unordered_map 哈希映射
unordered_multimap 哈希多重映射

无序关联容器/哈希容器

  • 哈希容器的底层实现采用的是哈希表的存储结构。
  • 哈希容器内部存储的键值对是无序的,各键值对的存储位置取决于该键值对中的键。
  • 和有序关联式容器相比,哈希容器擅长通过指定键查找对应的值(平均时间复杂度为 O(1));但对于使用迭代器遍历容器中存储的元素,哈希容器的执行效率则不如有序关联式容器。

【 2. 迭代器 】

  • 简单来讲,迭代器和 C++ 的指针非常类似,它可以是需要的任意类型,通过迭代器可以指向容器中的某个元素,如果需要,还可以对该元素进行读/写操作。
  • 详见:【C++ STL迭代器】iterator

【 3. 适配器 】

  • 我们所说的这个“适配器”,和生活中常见的电源适配器中“适配器”的含义非常接近。我们知道,无论是电脑、手机还是其它电器,充电时都无法直接使用 220V 的交流电,为了方便用户使用,各个电器厂商都会提供一个适用于自己产品的电源线,它可以将 220V 的交流电转换成适合电器使用的低压直流电。
    从用户的角度看,电源线扮演的角色就是将原本不适用的交流电变得适用,因此其又被称为电源适配器。
  • 再举一个例子,假设一个代码模块 A,它的构成如下所示:
class A{
public:
   void f1(){}
  void f2(){}
 void f3(){}
 void f4(){}
};
  • 现在我们需要设计一个模板 B,但发现,其实只需要组合一下模块 A 中的 f1()、f2()、f3(),就可以实现模板 B 需要的功能。其中 f1() 单独使用即可,而 f2() 和 f3() 需要组合起来使用,如下所示:
class B
{
private:
   A * a;
public:
   void g1()
   {
       a->f1();
   }
   void g2()
   {
       a->f2();
       a->f3();
   }
};
  • 可以看到,就如同是电源适配器将不适用的交流电变得适用一样,模板 B 将不适合直接拿来用的模板 A 变得适用了,因此我们可以 将模板 B 称为 B 适配器
  • 容器适配器也是同样的道理,简单的理解 容器适配器,其就是 将不适用的序列式容器(包括 vector、deque 和 list)变得适用。容器适配器的底层实现和模板 A、B 的关系是完全相同的,即通过封装某个序列式容器,并重新组合该容器中包含的成员函数,使其满足某些特定场景的需要。
  • 容器适配器本质上还是容器,只不过此容器模板类的实现,利用了大量其它基础容器模板类中已经写好的成员函数。当然,如果必要的话,容器适配器中也可以自创新的成员函数。
  • 需要注意的是,STL 中的 容器适配器内部使用的基础容器并不是固定的,用户可以在满足特定条件的多个基础容器中自由选择。
  • STL 提供了 3 种容器适配器,分别为 stack 栈适配器、queue 队列适配器以及 priority_queue 优先权队列适配器。其中,各适配器所使用的默认基础容器以及可供用户选择的基础容器,如表 所示。
容器适配器基础容器筛选条件
基础容器需包含以下成员函数:
满足条件的基础容器默认使用的基础容器
stackempty()
size()
back()
push_back()
pop_back()
vector、deque、list。deque
queueempty()
size()
front()
back()
push_back()
pop_front()
deque、list。deque
priority_queueempty()
size()
front()
push_back()
pop_back()
vector、deque。vector
  • 不同场景下,由于不同的序列式容器其底层采用的数据结构不同,因此容器适配器的执行效率也不尽相同。但通常情况下,使用默认的基础容器即可。当然,我们也可以手动修改,具体的修改容器适配器基础容器的方法,后续讲解具体的容器适配器会详细介绍。
  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MR_Promethus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值