C++STL六大组件

C++ STL 概念

STL(标准模板库,Standard Template Library) ,是 C++ 提供的标准模板类库,核心定义如下:

  1. 它以模板泛型编程的方式,对常用数据结构(动态数组、链表、哈希表、红黑树、栈、队列等)进行封装;
  2. 同时提供通用的泛型算法(排序、查找、遍历、拷贝等),实现数据结构与算法解耦;
  3. 核心由容器、迭代器、算法、函数对象、适配器、空间配置器六大部分组成,可跨类型复用,大幅提升开发效率。

C++ STL 容器分类

一、容器整体分类

1. 序列式容器(底层为线性结构,元素有序、可重复)

表格

容器 底层数据结构 版本 核心特点
string 字符顺序表 C++98 专门处理字符串
vector 动态顺序表(连续内存) C++98 随机访问快,尾部增删高效
list 双向循环链表 C++98 任意位置插入删除快,不支持随机访问
deque 分段连续数组(动态二维数组) C++98 头尾增删高效,支持随机访问
array 静态顺序表 C++11 固定大小数组,栈上分配
forward_list 单向循环链表 C++11 空间开销更小,仅支持单向遍历

2. 关联式容器(底层树形 / 哈希,自动排序 / 快速查找)

(1)树形结构(C++98,红黑树,有序)
  • map:键值对,key 唯一,默认升序
  • set:纯 key 集合,元素唯一,默认升序
  • multimap:键值对,key 可重复
  • multiset:纯 key 集合,元素可重复
(2)哈希结构(C++11,哈希表,无序,查找更快)
  • unordered_map:无序键值对,key 唯一
  • unordered_set:无序集合,元素唯一
  • unordered_multimap:无序键值对,key 可重复
  • unordered_multiset:无序集合,元素可重复

二、面试高频考点(思维导图 5 点核心)

1. 容器常用接口

通用:size()empty()clear()begin()end()

  • vectorpush_back()pop_back()reserve()resize()
  • listpush_front()pop_front()splice()
  • map/unordered_mapinsert()erase()find()operator[]

2. 底层数据结构(必背)

  • 连续内存:vectorarraystring
  • 链表:listforward_list
  • 分段数组:deque
  • 红黑树:map/set/multimap/multiset
  • 哈希表:unordered_*系列

3. 应用场景

  • 频繁随机访问、尾部增删 → vector
  • 频繁任意位置插入删除 → list
  • 头尾高频操作 → deque
  • 有序键值查找 → map
  • 快速无序查找 → unordered_map

4. 高频容器区别(面试必问,精简版)

① vector vs list
  1. 底层:vector 动态数组;list 双向链表
  2. 访问:vector 支持随机访问[];list 不支持
  3. 增删:vector 中间插入删除 O (n);list 任意位置 O (1)
  4. 内存:vector 连续内存;list 节点分散,碎片多
② map vs set
  • map 存储<key,value>键值对;set 只存储 key
  • map 可通过 key 映射 value;set 用于去重、排序
③ map vs unordered_map
  1. 底层:map 红黑树;unordered_map 哈希表
  2. 有序性:mapkey 有序;unordered_map 无序
  3. 效率:map 查找 O (logn);unordered_map 平均 O (1)
  4. 稳定性:map 无哈希冲突;unordered_map 存在哈希冲突

5. 接口时间复杂度

  • vector随机访问:O (1);中间插入:O (n)
  • list插入删除:O (1);查找:O (n)
  • map查找 / 插入 / 删除:O (logn)
  • unordered_map平均 O (1),最坏 O (n)

C++ STL 迭代器

一、迭代器核心概念与作用

1. 迭代器模式概念

迭代器是行为型设计模式,提供一种统一方式遍历容器元素,无需暴露容器内部结构。

2. 迭代器作用

解耦容器算法,让算法可以透明操作容器数据,不用关心容器底层是数组、链表还是树结构,实现一套算法适配所有容器。

3. 迭代器本质

本质是指针的封装,是容器和算法之间的桥梁,模拟指针行为。


二、迭代器分类(面试必背)

1. 按功能遍历方向分类

表格

迭代器类型 移动能力 支持容器
正向迭代器 只能 ++ 向后遍历 所有 STL 容器
反向迭代器 只能 -- 向前遍历(rbegin()/rend() vector/list/map
双向迭代器 支持 ++-- 双向移动 listmapset
随机迭代器 支持 ++/--/+n/-n/[] 随机访问 vectordequestring

权限等级:随机迭代器 > 双向迭代器 > 正向迭代器

2. 按能否修改元素分类

  • 普通迭代器:可读可写,可修改指向的元素
  • const 迭代器:只读不可写,禁止修改元素,保证数据安全

三、如何给容器自定义迭代器(4 个核心重载要求)

  1. 构造:绑定容器底层结构(数组 / 链表节点等)
  2. 解引用与成员访问 :重载 operator*()operator->(),模拟指针取值
  3. 迭代器移动 :重载前置 / 后置 operator++(),双向容器额外重载 operator--()
  4. 迭代器比较 :重载 operator==()operator!=(),用于判断遍历边界

四、面试高频延伸考点(加分项)

  1. 失效问题
    • vector:扩容、中间插入删除会导致迭代器失效
    • list:仅删除当前迭代器会失效,其余不受影响
  2. 底层对应
    • 随机迭代器:原生指针即可实现
    • 双向迭代器:封装链表节点指针

C++ STL 算法

一、算法整体分类

1. 与数据结构相关算法

容器自带的成员方法,和容器底层强绑定,只能对应容器使用。

  • 例:list::sort()map::find()vector::erase()

2. 通用算法(<algorithm>头文件)

不依赖具体容器,通过迭代器操作数据,一套算法适配所有容器,分为两类:

  1. 不带仿函数的算法 :使用默认规则(如默认升序排序、默认相等判断)
    • 例:sortfindreversecopy
  2. 带有仿函数的算法 :支持传入仿函数 / 函数指针 /lambda ,自定义算法逻辑
    • 例:sort(v.begin(),v.end(),greater<int>()) 降序排序;可自定义比较规则、筛选规则

二、使用注意事项

  1. 头文件依赖 :通用算法必须包含头文件 <algorithm>
  2. 常见高频算法(面试必背)
    • 排序类:sort(快排,O (nlogn))、stable_sort(稳定排序)
    • 查找类:findbinary_search(二分查找,需有序)
    • 遍历修改:for_eachtransform
    • 最值 / 计数:max_elementmin_elementcount
  3. 时间复杂度(核心考点)
    • sort:O(nlogn)
    • find:O(n)
    • binary_search:O(logn)
    • for_each:O(n)

C++ STL 适配器

一、适配器模式概念

适配器是结构型设计模式 ,作用是复用已有组件,通过封装转换接口 ,让原有组件适配新的使用场景,不用修改底层实现。STL 适配器不自己实现底层结构,而是基于已有容器 / 迭代器 / 函数做二次封装


二、三大分类(面试必背)

1. 容器适配器(最常考)

对已有序列式容器进行封装,限定接口,实现特定数据结构:

表格

适配器 默认底层容器 核心特点
stack(栈) deque 后进先出 LIFO,只允许栈顶增删查
queue(队列) deque 先进先出 FIFO,只允许头尾操作
priority_queue(优先队列) vector 堆结构,默认大顶堆,自动维护最值

底层可手动更换:例 stack<int, vector<int>> st;

2. 迭代器适配器

对普通迭代器封装,改变遍历行为:

  • 反向迭代器reverse_iterator,如rbegin()/rend(),反转遍历方向
  • 插入迭代器、流迭代器等,适配不同遍历 / 插入场景

3. 函数适配器

对函数对象 / 函数指针封装,适配算法参数要求:

  • 常见:bindnot1not2mem_fun等,用于绑定参数、取反逻辑、适配成员函数

三、面试高频考点

  1. stack/queue 为什么不能用 list 做底层? 可以用,只是默认选deque,因为deque头尾操作效率最高。
  2. priority_queue 底层是堆,堆是大顶堆还是小顶堆? 默认大顶堆 ,可通过greater仿函数改为小顶堆。
  3. 适配器本质:复用现有组件,只修改对外接口,不修改底层实现。

C++ STL 仿函数

一、核心概念

仿函数(函数对象):让一个类的对象可以像普通函数一样调用使用 ,本质是重载了 operator() 的类。

二、实现方式

在自定义类中,重载圆括号运算符 operator(),即可将类对象变为可调用的仿函数。

极简示例

cpp 复制代码
struct Compare {
    bool operator()(int a, int b) {
        return a > b; // 自定义比较逻辑
    }
};

三、核心作用

  1. 定制 STL 通用算法功能 :给sortfindpriority_queue等算法传入自定义逻辑(排序规则、匹配规则),让算法灵活可扩展。
  2. 相比普通函数的优势
    • 可保存状态(类成员变量);
    • 类型安全,编译器可做类型检查;
    • 可被适配器修饰,适配更多场景。

四、面试高频考点

  1. 和普通函数、lambda 的区别
    • 普通函数:无状态,不可适配;
    • 仿函数:可存状态,兼容性强;
    • lambda:语法简洁,本质也是匿名仿函数。
  2. 典型使用场景
    • sort(v.begin(),v.end(),Compare()) 自定义排序;
    • priority_queue<int,vector<int>,greater<int>> 小顶堆。

C++ STL 空间配置器

1. 什么是空间配置器 & 作用

概念

空间配置器(allocator)是 STL 的内存管理组件,负责容器的内存申请、释放、对象构造、析构,隔离容器与底层内存操作。

作用

  • 统一管理容器内存,将内存分配对象构造分离;
  • 优化小块内存分配效率,减少内存碎片;
  • 屏蔽平台内存差异,实现跨平台。

2. 为什么需要空间配置器

  1. STL 容器频繁创建 / 销毁大量小块内存 ,直接用malloc/free效率低、易产生内存碎片;
  2. 普通内存分配仅分配空间,配置器可同时处理内存分配 + 对象构造
  3. 针对大小块内存做分层优化,提升性能。

3. SGI‑STL 两级空间配置器实现原理

一级空间配置器

  • 应用场景 :处理大于 128 字节的大块内存
  • 原理 :直接封装mallocfree,额外增加内存不足时的异常处理机制(内存池兜底 / 抛出异常)

二级空间配置器(重点)

  • 应用场景:处理 **≤128 字节 ** 的小块内存
  • 核心原理
    1. 封装内存池,预先申请一大块连续内存,拆分复用;
    2. 维护16 个哈希桶,分别管理 8/16/24...128 字节的内存块;
    3. 小块内存申请 / 释放直接从对应哈希桶取放,避免频繁调用系统接口,减少碎片。

4. 空间配置器优缺点

优点

  1. 小块内存分配速度更快,减少系统调用开销;
  2. 有效减少内存碎片;
  3. 内存分配与对象构造分离,灵活可控。

缺点

  1. 内存池会占用部分闲置内存,存在一定内存浪费;
  2. 二级配置器仅针对小块内存优化,大块内存无提升。

相关推荐
啦啦啦啦啦zzzz6 分钟前
数据结构:红黑树理论
数据结构·c++·红黑树
Yolo_TvT11 分钟前
C++:默认构造函数
c++
z落落18 分钟前
C# 四种特殊类:抽象类、密封类、静态类、部分类
开发语言·c#
VidDown44 分钟前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
装不满的克莱因瓶1 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
weixin_523185322 小时前
Java基础知识总结(四):引用数据类型与参数传递机制
java·开发语言·python
Nayxxu2 小时前
Claude API 生产稳定性设计:超时、降级、备用模型和告警怎么做
开发语言·php
王cb2 小时前
WinRT Server and Client c#
开发语言·c#
小欣加油2 小时前
leetcode994 腐烂的橘子
数据结构·c++·算法·leetcode·bfs
Selina K2 小时前
C中日历时间转换
c语言·开发语言