C++ STL (标准模板库)

29 Aug 2025 | 13 分钟阅读

在 C++ 中,标准模板库(STL)是一组强大的模板类和函数,提供了通用的数据结构和算法。它允许开发人员使用通用编程组件的经过优化的实现,例如 动态数组链表队列、集合、映射 以及各种算法。

简单示例

让我们通过一个示例来演示 C++ 中的 STL 函数。

示例

编译并运行

输出

Sorted numbers: 1 2 4 7 8

解释

在此示例中,vector <int> 是一个存储整数的 STL 容器。Sort() 是一个对 vector 进行排序的 STL 算法。基于范围的语法使用递归来达到并打印循环中的元素。

STL 的特点

C++ 中 STL 的几个特点如下:

  • 可重用性:代码通过可重用组件减少了重复。
  • 效率:它包含经过适应、预先测试的算法和容器。
  • 泛型编程:它使用模板来处理任何数据类型。
  • 一致性:它在容器、算法和迭代器等各种组件中提供了统一的结构。

STL 的类型

C++ STL 主要分为四类:

  • 容器
  • 算法
  • 迭代器
  • 函数对象(Functors)

现在,我们将逐一讨论这些 C++ STL 类型。

STL 容器

容器可以被描述为保存相同类型数据的对象。容器用于实现不同的数据结构,例如数组、列表、树等。

以下是提供所有容器的详细信息以及它们关联的头文件和迭代器类型的容器:

容器描述头文件迭代器
vectorvector 是一个类,它创建了一个动态数组,允许在末尾进行插入和删除。<vector>随机访问
listlist 是序列容器,允许在任何位置进行插入和删除。<list>双向
dequedeque 是双端队列,允许在两端进行插入和删除。<deque>随机访问
setset 是用于存储唯一集合的关联容器。<set>双向
multisetmultiset 是用于存储非唯一集合的关联容器。<set>双向
mapmap 是用于存储唯一的键值对的关联容器,即每个键只与一个值相关联(一对一映射)。<map>双向
multimapmultimap 是一个关联容器,用于存储键值对,并且每个键可以与多个值相关联。<map>双向
stack它遵循后进先出(LIFO)原则。<stack>无迭代器
queue它遵循先进先出(FIFO)原则。<queue>无迭代器
priority_queue第一个出队的元素始终是优先级最高的元素。<queue>无迭代器

容器的分类

1. 序列容器

序列容器按线性顺序存储元素,并允许按索引访问。

  • Vector:一个动态数组,可自动调整大小。
  • Deque:一个双端队列,允许在两端快速插入和删除。
  • List:一个双向链表,支持在任何位置快速插入和删除。

C++ 序列容器示例

让我们以一个实例来演示 C++ 中的序列容器。

示例

编译并运行

输出

Vector elements: 10 20 30 40 50

解释

在此示例中,我们使用元素 {10, 20, 30, 40} 初始化一个 vector,然后使用 push_back() 函数在末尾添加 50。最后,使用基于范围的 for 循环打印所有 vector 元素。

2. 关联容器

关联容器以基于键的排序顺序存储元素,并自动维护此顺序。它们将数据组织为键值对,并提供基于键的高效查找、插入和删除。

  • Set:它以排序顺序存储唯一元素。
  • Map:它存储唯一的排序键值对。
  • Multiset:它类似于 set,但允许重复元素。
  • Multimap:它类似于 MAP,但允许重复键。

C++ 关联容器示例

让我们以一个实例来演示 C++ 中的关联容器。

示例

编译并运行

输出

ID: 101, Name: Alice
ID: 102, Name: Bob
ID: 103, Name: Charlie

解释

在此示例中,我们采用了一个 map 容器,它以排序顺序存储键值对。它将学生 ID(101、102、103)作为键,将姓名(Alice、Bob、Charlie)作为值插入。最后,它使用基于范围的 for 循环遍历 map,以打印每个 ID 和姓名。

3. 无序关联容器

这些容器是 C++ STL 的重要组成部分,它们以不精确的顺序存储元素,并通过哈希表实现快速检索。无序关联容器不维护任何顺序。C++ 中有几个无序关联容器,如下所示:

  • 无序集合:它以无序方式存储唯一元素。
  • 无序映射:它以无序方式存储具有唯一键的键值对。
  • 无序多集:它类似于 unordered_set,但允许重复元素。
  • 无序多重映射:它类似于 unordered_map,但允许具有相同键的多个元素。

C++ 无序关联容器示例

让我们以一个实例来演示 C++ 中的无序关联容器。

示例

编译并运行

输出

Mango: 5
Banana: 20
Apple: 10
Orange: 15

解释

在此示例中,我们使用了一个 unordered_map,它以无序方式存储键值对以实现快速查找。它使用水果名称作为键和它们的计数作为值初始化 map,然后插入“Mango”。最后,它使用基于范围的 for 循环遍历 map,以打印每种水果及其计数。

注意:每个容器类都包含一组可用于操作其内容的函数。

C++ 容器示例

让我们看一个演示 C++ 中容器的示例。

示例

编译并运行

输出

Vector elements: 10 20 30 40 50 
List elements: 100, 200, 300, 400 
Set elements: 5 10 15 20 
Map elements:
1 -> One
2 -> Two
3 -> Three

解释

给定的程序演示了 STL 迭代器,它遍历不同的容器(vector、list、set 和 map)。迭代器允许按顺序访问元素,这些元素从 begin() 开始,在 end() 函数结束。vector 和 list 维护插入顺序,set 自动对元素进行排序,map 按键的排序顺序存储键值对。

STL 迭代器

在 C++ 中,STL 迭代器是指针状的实体,用于访问容器中的各个元素。迭代器按顺序从一个元素移动到另一个元素。这个过程称为遍历容器。

迭代器主要包含两个函数:

  • begin():begin() 成员函数返回指向 vector 第一个元素的迭代器。
  • end():end() 成员函数返回指向容器最后一个元素之后的迭代器。

迭代器类别

迭代器主要分为五类:

1. 输入迭代器

输入迭代器是一种迭代器,它允许程序通过解引用来读取容器中的值,但不允许修改这些值。它是单向遍历,意味着它只能递增(++),不能递减(--)。输入迭代器通常用于单次遍历算法,其中数据按顺序读取。

2. 输出迭代器

输出迭代器与输入迭代器类似,只是它允许程序修改容器的值,但不允许读取它。它是一个单向迭代器。它是一个只写迭代器。

3. 前向迭代器

前向迭代器使用 (++) 运算符在容器中导航。前向迭代器一次遍历容器的每个元素。

4. 双向迭代器

双向迭代器与前向迭代器类似,但具有附加功能,它可以向前和向后遍历容器。这种双向遍历能力使其可以递增 (++) 和递减 (--),比前向迭代器更通用。

5. 随机访问迭代器

随机访问迭代器可用于访问容器的随机元素。随机访问迭代器具有双向迭代器的所有功能,并且还具有一项附加功能,即指针加法。通过使用指针加法运算,我们可以访问容器的随机元素。

迭代器支持的操作

迭代器元素访问读取写入递增操作比较
输入->v = *p ++==,!=
输出  *p = v++ 
前向->v = *p*p = v++==,!=
双向->v = *p*p = v++,--==,!=
随机访问->,[ ]v = *p*p = v++,--,+,-,+=,--===,!=,<,>,<=,>=

C++ 迭代器示例

让我们看一个演示 C++ STL 中迭代器的示例。

示例

编译并运行

输出

Input Iterator: 10
100 (Output Iterator writes 100)
Forward Iterator: 99 2 3 4 
Bidirectional Iterator: 15
After decrement: 10
Random Access Iterator (+2): 30
Random Access Iterator (-1): 20
Random Access Iterator with index: 30

解释

此程序演示了所有类型的 STL 迭代器:输入(只读)、输出(只写)、前向(读/写/递增)、双向(支持 ++, --)和随机访问(+, -, [ ])。使用不同的 STL 容器(vector、list、set)来展示它们各自的迭代器行为。

STL 算法

算法是标准模板库(STL)中的预定义函数,它们作用于容器的元素来处理、操作或分析其内容。

注意事项

  • 算法提供了大约 60 种算法函数来执行复杂的操作。
  • 标准算法允许我们同时处理两种不同类型的容器。
  • 算法不是容器的成员函数,而是独立的模板函数。
  • 算法节省了大量时间和精力。
  • 如果我们想访问 STL 算法,我们必须在程序中包含 <algorithm> 头文件。

STL 算法类别

  • 非变异算法:非变异算法是指不修改容器内容的算法。它们作用于元素而不改变其值或顺序。这些算法通常用于根据特定条件搜索、比较、计数或查找元素。这些算法可用于所有容器对象,并利用前向迭代器。
  • 变异算法:变异算法是可用于更改容器值的算法。它们还可用于更改元素出现的顺序。
  • 排序算法:排序算法是用于对容器中的元素进行排序的变异算法。
  • 集合算法:集合算法也称为排序范围算法。此算法用于对容器执行某些功能,极大地提高了程序的效率。
  • 关系算法:关系算法是用于处理数值数据的算法。它们主要设计用于对容器中的所有元素执行数学运算。

C++ 算法示例

让我们看一个演示 C++ STL 中算法的示例程序。

示例

编译并运行

输出

Found 30 in vector
Vector after reverse: 50 40 30 20 10 
Vector after sorting: 10 20 30 40 50 
Set union: 1 2 3 5 6 7 
The sum of vector elements: 150

解释

此程序展示了 STL 算法:find(非变异)、reverse(变异)、sort(排序)、set_union(集合算法)和 accumulate(关系)。这些函数简化了对 vector 和 set 等容器的操作。该程序高效地执行搜索、修改、排序、合并和数值运算。

STL 函数对象

函数对象也称为“functor”。函数对象是一个包含至少一个 operator() 函数定义的类。这意味着,如果我们声明一个具有 operator() 函数定义的类的对象 'd',我们可以像常规函数一样使用对象 'd'。

语法

它具有以下语法:

C++ 函数对象示例

让我们看一个演示 C++ STL 中 Functors 的示例。

示例

编译并运行

输出

Vector after multiplication by 3: 3 6 9 12 15 

解释

此程序定义了一个 Functor MultiplyBy,它使用 operator() 将每个元素乘以给定的因子。STL transform() 算法将 Functor 应用于 vector 的所有元素,从而高效地修改它们。Functor 通过允许自定义操作(如乘法)使算法更具灵活性。

C++ STL 选择题

1. 在 C++ 中使用 STL 的主要优势是什么?

  1. 使用 C++ 中的 STL 时,执行时间缩短了一半。
  2. STL 的实现提供了经过彻底测试的可重用组件。
  3. 使用 STL 消除了对指针的必要性。
  4. 它提供了 GUI 组件。
 

答案:b) STL 的实现提供了经过彻底测试的可重用组件。


2. 如果您尝试向 set 中插入重复元素,会发生什么?

  1. 它会插入重复项。
  2. 插入操作默认会替换任何现有元素。
  3. 重复插入的尝试不会改变数据存储。
  4. 将发生运行时错误。
 

答案:c) 重复插入的尝试不会改变数据存储。


3. 以下关于 STL 中 map 容器的陈述哪项是正确的?

  1. 允许重复键。
  2. 以随机顺序维护元素。
  3. 系统存储唯一的键值组合。
  4. 数据结构维护不带任何值的键。
 

答案:c) 系统存储唯一的键值组合。


4. 如果您向 set 中插入重复元素,会发生什么?

  1. Map 容器允许将现有元素替换为新元素。
  2. 数据结构在其内容中接受两个等效元素。
  3. 它会引发运行时错误。
  4. 重复项将被忽略。
 

答案:d) 重复项将被忽略。


5. 以下关于 STL 的陈述哪项是错误的?

  1. STL 框架通过模板实现泛型编程。
  2. STL 容器自动管理内存。
  3. STL 算法能够修改其包含元素的大小。
  4. STL 提供经过验证的优化解决方案。
 

答案:c) STL 算法能够修改其包含元素的大小。


下一个主题C++ Vectors