C++ 系列 STL 标准库

2023年 10月 16日 48.7k 0

STL

什么是 STL

STL,中文可译为标准模板库或者泛型库,其包含有大量的模板类和模板函数,是 C++ 提供的一个基础模板的集合,用于完成诸如输入/输出、数学计算等功能。

STL 有什么用

以 C++ 定义数组的操作为例,在 C++ 中如果定义一个数组,可以采用如下方式:

int a[n];

这种定义数组的方法需要事先确定好数组的长度,即 n 必须为常量,这意味着,如果在实际应用中无法确定数组长度,则一般会将数组长度设为可能的最大值,但这极有可能导致存储空间的浪费。

所以除此之外,还可以采用在堆空间中动态申请内存的方法,此时长度可以是变量:

int *p = new int[n];

这种定义方式可根据变量 n 动态申请内存,不会出现存储空间浪费的问题。但是,如果程序执行过程中出现空间不足的情况时,则需要加大存储空间,此时需要进行如下操作:

  • 新申请一个较大的内存空间,即执行int * temp = new int[m];

  • 将原内存空间的数据全部复制到新申请的内存空间中,即执行memecpy(temp, p, sizeof(int)*n);

  • 将原来的堆空间释放,即执行delete [] p; p = temp;

  • 而完成相同的操作,如果采用 STL 标准库,则会简单很多。下面是使用向量模板类 vector 实现以上功能的示例:

    // 定义 a 数组,当前数组长度为 0,
    // 但和普通数组不同的是,此数组 a 可以根据存储数据的数量【自动变长】
    vector  a;
    // 向数组 a 中添加 10 个元素
    for (int i = 0; i < 10 ; i++)
        a.push_back(i)
    // 还可以手动调整数组 a 的大小
    a.resize(100);
    a[90] = 100;
    // 还可以直接删除数组 a 中所有的元素,此时 a 的长度变为 0
    a.clear();
    // 重新调整 a 的大小为 20,并存储 20 个 -1 元素。
    a.resize(20, -1)
    

    总结来说:

    STL 是 模板类 和 模板函数 的集合

    • 模板类 = 容器(数组、对象等等放数据)
    • 模板函数 = 读写这些容器中数据的函数(算法)

    之所以都要使用模板,是因为数据类型多样,必须使用泛型技术

    STL 基本组成

    通常认为,STL 是由容器、算法、迭代器、函数对象、适配器、内存分配器这 6 部分构成,其中后面 4 部分是为前 2 部分服务的,它们各自的含义如下表所示

    STL的组成 含义
    容器 一些封装数据结构的模板类,例如 vector 向量容器、list 列表容器等
    算法 STL 提供了非常多(大约 100 个)的数据结构算法,它们都被设计成一个个的模板函数,这些算法在 std 命名空间中定义,其中大部分算法都包含在头文件 中,少部分位于头文件
    迭代器 在 C++ STL 中,对容器中数据的读和写,是通过迭代器完成的,扮演着容器和算法之间的胶合剂
    函数对象 如果一个类将 () 运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象(又称仿函数)
    适配器 可以使一个类的接口(模板的参数)适配成用户指定的形式,从而让原本不能在一起工作的两个类工作在一起。值得一提的是,容器、迭代器和函数都有适配器
    内存分配器 为容器类模板提供自定义的内存申请和释放功能,由于往往只有高级用户才有改变内存分配策略的需求,因此内存分配器对于一般用户来说,并不常用

    C++ 标准库中有这 13 个标准头文件

    STL 容器

    STL 容器是什么

    容器的简单理解:模板类的集合,但和普通模板类不同的是,容器中封装的是组织数据的方法(也就是数据结构)

    STL 容器的分类

    STL 提供有 3 类标准容器,分别是序列容器、排序容器和哈希容器,其中后两类容器有时也统称为关联容器

    容器种类 功能
    序列容器 主要包括 vector 向量容器、list 列表容器以及 deque 双端队列容器。之所以被称为序列容器,是因为元素在容器中的位置同元素的值无关,即容器不是排序的,顺序取决于插入顺序。将元素插入容器时,指定在什么位置,元素就会位于什么位置
    排序容器 包括 set 集合容器、multiset 多重集合容器、map 映射容器以及 multimap 多重映射容器。排序容器中的元素默认是由小到大排序好的,即便是插入元素,元素也会插入到适当位置。所以关联容器在查找时具有非常好的性能
    哈希容器 包括 unordered_set 哈希集合、unordered_multiset 哈希多重集合、unordered_map 哈希映射以及 unordered_multimap 哈希多重映射。和排序容器不同,哈希容器中的元素是未排序的,元素的位置由哈希函数确定

    以上 3 类容器的存储方式完全不同,因此使用不同容器完成相同操作的效率也大不相同。所以在实际使用时,要善于根据想实现的功能,选择合适的容器

    STL 迭代器

    STL 迭代器是什么

    无论是序列容器还是关联容器,最常做的操作无疑是遍历容器中存储的元素,而实现此操作,多数情况会选用“迭代器(iterator)”来实现

    我们知道,尽管不同容器的内部结构各异,但它们本质上都是用来存储大量数据的,换句话说,都是一串能存储多个数据的存储单元。因此,诸如数据的排序、查找、求和等需要对数据进行遍历的操作方法应该是类似的。

    既然类似,完全可以利用泛型技术,将它们设计成适用所有容器的通用算法,从而将容器和算法分离开。但实现此目的需要有一个类似中介的装置,它除了要具有对容器进行遍历读写数据的能力之外,还要能对外隐藏容器的内部差异,从而以统一的界面向算法传送数据

    这是泛型思维发展的必然结果,于是迭代器就产生了

    STL 迭代器分类

    常用的迭代器按功能强弱分为输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器 5 种。

    输入迭代器和输出迭代器比较特殊,它们不是把数组或容器当做操作对象,而是把输入流/输出流作为操作对象

    我们先主要关注后面三种迭代器:

  • 前向迭代器
    假设 p 是一个前向迭代器,则 p 支持 ++p,p++,*p 操作,还可以被复制或赋值,可以用 ==!= 运算符进行比较。此外,两个正向迭代器可以互相赋值。

  • 双向迭代器
    双向迭代器具有正向迭代器的全部功能,除此之外,假设 p 是一个双向迭代器,则还可以进行 --p 或者 p-- 操作(即一次向后移动一个位置)。

  • 随机访问迭代器
    随机访问迭代器具有双向迭代器的全部功能。除此之外,假设 p 是一个随机访问迭代器,i 是一个整型变量或常量,则 p 还支持以下操作:

    • p+=i:使得 p 往后移动 i 个元素
    • p-=i:使得 p 往前移动 i 个元素
    • p+i:返回 p 后面第 i 个元素的迭代器
    • p-i:返回 p 前面第 i 个元素的迭代器
    • p[i]:返回 p 后面第 i 个元素的引用

    此外,两个随机访问迭代器 p1、p2 还可以用 、= 运算符进行比较。另外,表达式 p2-p1 也是有定义的,其返回值表示 p2 所指向元素和 p1 所指向元素的序号之差(也可以说是 p2 和 p1 之间的元素个数减一)

    是 C++ 11 标准中不同容器指定使用的迭代器类型

    容器 对应的迭代器类型
    array 随机访问迭代器
    vector 随机访问迭代器
    deque 随机访问迭代器
    list 双向迭代器
    set / multiset 双向迭代器
    map / multimap 双向迭代器
    forward_list 前向迭代器
    unordered_map / unordered_multimap 前向迭代器
    unordered_set / unordered_multiset 前向迭代器
    stack 不支持迭代器
    queue 不支持迭代器

    注意,容器适配器 stack 和 queue 没有迭代器,它们包含有一些成员函数,可以用来对元素进行访问

    STL 迭代器有什么用

    下面就以 vector 容器为例,带领大家实际感受迭代器的用法和功能。vector 支持随机访问迭代器,因此遍历 vector 容器有以下几种做法。下面的程序中,每个循环演示了一种做法:

    #include
    // 需要引入 vector 头文件
    #include
    using namespace std;
    int main()
    {
        vector v{1,2,3,4,5,6,7,8,9,10}; // v 被初始化成有 10 个元素
        cout

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论