C++27 STL基础讲解

一、STL 总体架构

STL是 C++ 标准库的核心组成部分。它不是单一的概念,而是由五个相互协作的组件组成的完整体系。这五个组件就像一个精密的钟表,每个部件都有自己的职责,协同工作。

想象一下这五个组件的关系:

  • 容器是各种盒子(书架、衣柜、抽屉)

  • 算法操作方法(怎么放、怎么取、怎么整理)

  • 迭代器手或工具(连接你和盒子的桥梁)

  • 仿函数智能工具(带特殊功能的夹子、剪刀)

  • 适配器转换接口(把方孔变成圆孔的转接头)

二、五大组件详解

1. 容器(Containers)—— 数据的“盒子”

容器就是装数据的各种“容器”,就像现实中的数组、链表、树、哈希表等数据结构的模板实现。

1.1 容器分类(三层理解)

第一层:按存储方式分

  • 序列容器:元素按线性顺序排列

    • vector:动态数组(像可以自动扩容的货架)

    • deque:双端队列(像两头的传送带)

    • list:双向链表(像一串珍珠项链)

    • forward_list:单向链表(只能向前走的项链)

    • array:固定数组(固定大小的储物格)

  • 关联容器:元素按键值排序存储(像字典)

    • set:唯一键集合(不允许重复的集合)

    • multiset:可重复键集合(允许重复的集合)

    • map:键值对映射(像电话簿:名字→号码)

    • multimap:可重复键的映射(同名可以有多个号码)

  • 无序关联容器:哈希表实现(像乱放但能快速找到的抽屉)

    • unordered_set:无序唯一集合

    • unordered_map:无序键值映射

    • 等等...

  • 容器适配器:特殊用途的包装

    • stack:栈(后进先出,像叠盘子)

    • queue:队列(先进先出,像排队)

    • priority_queue:优先队列(按优先级出队,像医院急诊)

1.2 容器的核心特性

关键点1:模板
所有容器都是类模板,可以存储任何类型:

cpp

vector<int> // 存int vector<string> // 存string vector<vector<int>> // 存vector(二维数组)

关键点2:内存管理

  • 值语义:容器存储的是对象的副本

  • RAII原则:自动管理内存,离开作用域自动释放

  • 异常安全:保证基本异常安全

关键点3:接口统一
所有容器都提供类似的接口:

  • size():元素个数

  • empty():是否为空

  • begin()/end():迭代器

  • clear():清空


2. 算法(Algorithms)—— 操作的“说明书”

算法是操作数据的通用方法,就像一本说明书,告诉你如何对数据进行排序、查找、复制、删除等操作。

2.1 算法特点

关键特点1:通用性
算法不关心具体容器类型,只通过迭代器操作数据:

// 同样的sort算法,可以对vector、deque、array等排序 sort(vector.begin(), vector.end()); sort(deque.begin(), deque.end());

关键特点2:函数模板
算法都是函数模板,可以处理各种数据类型:

sort(int_vector.begin(), int_vector.end()); // 排序int sort(string_vector.begin(), string_vector.end()); // 排序string

关键特点3:迭代器依赖
算法通过迭代器访问容器元素,不直接操作容器本身。

2.2 算法分类

常用算法类别:

  1. 排序算法

    • sort:快速排序

    • stable_sort:稳定排序(相等元素保持原顺序)

    • partial_sort:部分排序

  2. 查找算法

    • find:线性查找

    • binary_search:二分查找(要求已排序)

    • lower_bound/upper_bound:边界查找

  3. 修改算法

    • copy:复制

    • fill:填充

    • replace:替换

    • remove:删除(实际是移动,需要配合erase)

  4. 数值算法

    • accumulate:累加

    • inner_product:内积

    • adjacent_difference:相邻差

  5. 集合算法

    • set_union:并集

    • set_intersection:交集

    • set_difference:差集

重要概念:算法复杂度

cpp

sort() // O(n log n) - 快排 find() // O(n) - 线性查找 binary_search() // O(log n) - 二分查找

3. 迭代器(Iterators)—— 访问的“指针”

迭代器是连接容器和算法的桥梁,它像是一个智能指针,知道如何在容器中移动并访问元素。

3.1 迭代器的作用

桥梁作用:

text

容器(数据存储) ←→ 迭代器(访问接口) ←→ 算法(操作逻辑)

关键能力:

  1. 遍历:逐个访问容器元素

  2. 访问:读写容器元素

  3. 连接:让算法可以操作不同容器

3.2 迭代器分类(五种)

理解层次:从简单到复杂

  1. 输入迭代器(Input Iterator)

    • 只能,不能写

    • 只能向前移动(单次)

    • 一次性读取器

    • 例子:从键盘读取数据

  2. 输出迭代器(Output Iterator)

    • 只能,不能读

    • 只能向前移动

    • 打印机

    • 例子:向屏幕输出

  3. 前向迭代器(Forward Iterator)

    • 可以读写

    • 只能向前移动

    • 可以多次遍历

    • 例子:单向链表

  4. 双向迭代器(Bidirectional Iterator)

    • 可以向前向后移动

    • 可以读写

    • 例子:双向链表、红黑树

  5. 随机访问迭代器(Random Access Iterator)

    • 可以任意跳跃访问

    • 支持所有指针运算

    • 例子:数组、vector、deque

3.3 迭代器失效问题

重要警告:某些操作会使迭代器失效!

vector的典型问题:

cpp

vector<int> v = {1, 2, 3}; auto it = v.begin() + 1; // 指向2 v.push_back(4); // 可能导致重新分配内存 // 此时it失效!不能再使用

不同容器的失效规则:

  • vector:插入/删除可能导致所有迭代器失效

  • deque:中间插入/删除会使所有迭代器失效

  • list/set/map:只影响被删除元素的迭代器


4. 仿函数(Functors)—— 行为的“函数对象”

仿函数是行为像函数的对象,它实际上是一个重载了()运算符的类对象

4.1 为什么需要仿函数?

传统函数指针的局限性:

  1. 无法携带状态

  2. 无法内联优化

  3. 类型不安全

仿函数的优势:

  1. 可以保存状态

  2. 编译器可以内联优化

  3. 对象,有类型信息

4.2 仿函数的使用

简单示例:

cpp

// 定义一个仿函数类 struct AddValue { int value; AddValue(int v) : value(v) {} // 重载()运算符 int operator()(int x) const { return x + value; } }; // 使用 AddValue add5(5); int result = add5(10); // 调用add5.operator()(10),返回15
4.3 STL中的预定义仿函数

算术运算:

  • plus<T>:加法

  • minus<T>:减法

  • multiplies<T>:乘法

  • divides<T>:除法

  • modulus<T>:取模

  • negate<T>:取负

比较运算:

  • equal_to<T>:等于

  • not_equal_to<T>:不等于

  • greater<T>:大于

  • less<T>:小于

  • greater_equal<T>:大于等于

  • less_equal<T>:小于等于

逻辑运算:

  • logical_and<T>:与

  • logical_or<T>:或

  • logical_not<T>:非

使用示例:

cpp

// 使用greater进行降序排序 sort(v.begin(), v.end(), greater<int>());
4.4 现代替代品:Lambda表达式

C++11引入lambda表达式,很多情况下替代仿函数:

// 传统仿函数 struct Compare { bool operator()(int a, int b) { return a > b; } }; sort(v.begin(), v.end(), Compare()); // Lambda表达式(更简洁) sort(v.begin(), v.end(), [](int a, int b) { return a > b; });

5. 适配器(Adapters)—— 接口的“转换器”

适配器是接口转换器,它修改现有组件的接口,使其适应新的需求。

5.1 三种适配器

1. 容器适配器

  • 基于现有容器提供新接口

  • 三种主要类型:

    • stack:基于deque/vector/list,提供栈接口

    • queue:基于deque/list,提供队列接口

    • priority_queue:基于vector,提供优先队列接口

示例:stack的实现原理

cpp

// stack内部包含一个deque template<typename T, typename Container = deque<T>> class stack { private: Container c; // 底层容器 public: void push(const T& value) { c.push_back(value); } void pop() { c.pop_back(); } T& top() { return c.back(); } // ... 其他操作 };

2. 迭代器适配器

  • 修改迭代器的行为

  • 主要类型:

    • reverse_iterator:反向迭代器

    • insert_iterator:插入迭代器

    • stream_iterator:流迭代器

示例:反向迭代器

cpp

vector<int> v = {1, 2, 3}; // 反向遍历 for (auto rit = v.rbegin(); rit != v.rend(); ++rit) { cout << *rit << " "; // 输出:3 2 1 }

3. 函数适配器

  • 修改函数对象的行为

  • 在C++11后,很多被bind/lambda替代

  • 主要类型:

    • binder1st/binder2nd:绑定参数(C++11前)

    • not1/not2:逻辑取反

示例:bind适配器(C++11)

cpp

// 绑定函数的第二个参数 auto add = [](int a, int b) { return a + b; }; auto add5 = std::bind(add, std::placeholders::_1, 5); cout << add5(10); // 输出15

三、五大组件如何协同工作

工作流程示例:排序一个vector

cpp

// 1. 容器:创建数据存储 vector<int> numbers = {5, 2, 8, 1, 9}; // 2. 迭代器:提供访问接口 auto begin = numbers.begin(); // 获取起始位置 auto end = numbers.end(); // 获取结束位置 // 3. 算法:执行排序操作 // 内部使用迭代器访问元素 sort(begin, end); // 可选:使用仿函数改变排序行为 sort(begin, end, greater<int>()); // 降序排序 // 4. 适配器:改变访问方式 // 反向输出 copy(numbers.rbegin(), numbers.rend(), ostream_iterator<int>(cout, " "));

整个过程的数据流:

text

数据 → 存入容器 → 迭代器访问 → 算法处理 → 结果输出

组件间的松耦合设计

关键设计思想:

  1. 容器和算法分离:算法通过迭代器操作容器,不依赖具体容器类型

  2. 迭代器作为粘合剂:统一了不同容器的访问方式

  3. 仿函数提供策略:允许自定义操作行为

  4. 适配器扩展功能:不改动原有代码,增加新功能

五、总结:五大组件的关系比喻

完整比喻:图书馆系统

  1. 容器= 书架、储物柜(各种存储设施)

    • vector:一排可以扩展的书架

    • list:用链条连接的书格

    • map:按书名排序的目录柜

    • set:不允许重复的珍本书架

  2. 算法= 图书管理方法

    • sort:按某种规则整理书籍

    • find:查找特定书籍

    • copy:复印书籍

    • remove:下架旧书

  3. 迭代器= 图书管理员的手/扫码枪

    • 可以指向特定位置

    • 可以移动到相邻位置

    • 可以读取书籍信息

    • 连接书架(容器)和管理方法(算法)

  4. 仿函数= 智能工具/规则

    • 按作者排序的规则

    • 按出版日期筛选的条件

    • 自动贴标签的机器

  5. 适配器= 转换接口

    • 把普通书架变成只能从顶部取书的"栈式书架"

    • 把书架变成只能从一端取书的"队列式书架"

    • 反向阅读器(从后向前读)

整个系统工作流程:
管理员(算法)使用扫码枪(迭代器)按照特定规则(仿函数)在书架(容器)上操作,通过特殊设备(适配器)满足特殊需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1142352.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

科哥PDF-Extract-Kit技巧:处理低质量扫描文档的方法

科哥PDF-Extract-Kit技巧&#xff1a;处理低质量扫描文档的方法 1. 引言&#xff1a;为何低质量扫描文档是OCR的“硬骨头” 在日常办公、学术研究和档案数字化过程中&#xff0c;我们经常需要从扫描版PDF文档中提取结构化信息——包括文字、表格、公式等。然而&#xff0c;许…

PDF-Extract-Kit性能对比:开源PDF工具横向评测

PDF-Extract-Kit性能对比&#xff1a;开源PDF工具横向评测 1. 选型背景与评测目标 在学术研究、工程文档处理和知识管理领域&#xff0c;PDF文件的智能信息提取已成为一项基础且关键的技术需求。传统PDF解析工具往往只能进行简单的文本抽取&#xff0c;难以应对复杂的版面结构…

手把手教程:实现上位机UART协议解析

手把手教你实现上位机UART协议解析&#xff1a;从零构建稳定通信链路你有没有遇到过这样的场景&#xff1f;调试一块新板子&#xff0c;串口飞线接好、代码烧录完成&#xff0c;满怀期待地打开串口助手——结果屏幕上一堆乱码跳动&#xff0c;偶尔冒出几个“温度: 255 C”&…

WS2812B数据格式解析与发送逻辑构建

深入WS2812B&#xff1a;从时序陷阱到稳定驱动的实战之路你有没有遇到过这样的情况&#xff1f;明明代码写得一丝不苟&#xff0c;颜色值也设置正确&#xff0c;可接上WS2812B灯带后&#xff0c;LED却“抽风”般乱闪、偏色&#xff0c;甚至尾部完全不亮&#xff1f;别急——这几…

PDF-Extract-Kit布局检测实战:解析文档结构的完整指南

PDF-Extract-Kit布局检测实战&#xff1a;解析文档结构的完整指南 1. 引言&#xff1a;为何需要智能PDF结构解析&#xff1f; 在科研、教育和企业办公场景中&#xff0c;PDF文档承载着大量结构化信息——从学术论文中的公式与表格&#xff0c;到财务报告中的图表与段落。然而…

PDF-Extract-Kit部署指南:混合云环境PDF处理方案

PDF-Extract-Kit部署指南&#xff1a;混合云环境PDF处理方案 1. 引言 1.1 背景与需求 在现代企业数字化转型过程中&#xff0c;PDF文档作为信息传递的重要载体&#xff0c;广泛应用于科研论文、财务报表、合同协议等场景。然而&#xff0c;传统PDF处理工具往往局限于文本提取…

SpringBoot 使用 spring.profiles.active 来区分不同环境配置

很多时候&#xff0c;我们项目在开发环境和生产环境的配置是不一样的&#xff0c;例如&#xff0c;数据库配置&#xff0c;在开发的时候&#xff0c;我们一般用测试数据库&#xff0c;而在生产环境&#xff0c;我们要用生产数据库&#xff0c;这时候&#xff0c;我们可以利用 p…

混元翻译1.5模型教程:自定义术语库管理实战

混元翻译1.5模型教程&#xff1a;自定义术语库管理实战 1. 引言 随着全球化进程的加速&#xff0c;高质量、可定制化的机器翻译需求日益增长。传统翻译模型虽然在通用场景下表现良好&#xff0c;但在专业领域&#xff08;如医疗、法律、金融&#xff09;中常因术语不准确而导…

C++28 STL容器--array

std::array 核心定位std::array 是 C11 引入的静态数组封装&#xff0c;本质是对 C 风格静态数组&#xff08;如 int arr[5]&#xff09;的 “现代化升级”&#xff0c;核心目标&#xff1a;保留 C 数组 “栈上分配、高效访问” 的优点&#xff1b;弥补 C 数组 “类型不安全、无…

HY-MT1.5-7B应用:专业领域文档翻译优化

HY-MT1.5-7B应用&#xff1a;专业领域文档翻译优化 1. 引言 随着全球化进程的加速&#xff0c;跨语言信息流通成为企业、科研机构乃至个人日常工作的关键环节。在众多翻译需求中&#xff0c;专业领域文档翻译因其术语密集、语境依赖性强、格式要求严格等特点&#xff0c;长期…

PDF-Extract-Kit详细步骤:构建PDF处理REST API

PDF-Extract-Kit详细步骤&#xff1a;构建PDF处理REST API 1. 引言 1.1 技术背景与业务需求 在当前数字化办公和学术研究的背景下&#xff0c;PDF文档已成为信息传递的主要载体。然而&#xff0c;PDF格式的封闭性导致其内容难以直接提取和再利用&#xff0c;尤其是在处理包含…

PDF-Extract-Kit OCR实战:中英文混合识别详细步骤

PDF-Extract-Kit OCR实战&#xff1a;中英文混合识别详细步骤 1. 引言 1.1 业务场景描述 在日常工作中&#xff0c;我们经常需要从PDF文档或扫描图片中提取文字内容&#xff0c;尤其是中英文混合的学术论文、技术报告和商务文件。传统的手动输入方式效率低下且容易出错&…

RS485半双工通信时序优化在STM32中的实践

RS485半双工通信时序优化在STM32中的实战精要工业现场&#xff0c;一条屏蔽双绞线横穿数十米&#xff0c;连接着PLC、变频器和温控仪表。上位机轮询指令刚发出&#xff0c;响应却迟迟不回——是线路干扰&#xff1f;还是协议解析出错&#xff1f;经验丰富的工程师知道&#xff…

PDF-Extract-Kit部署案例:学术期刊元数据提取系统

PDF-Extract-Kit部署案例&#xff1a;学术期刊元数据提取系统 1. 引言 1.1 业务场景描述 在科研与出版领域&#xff0c;大量学术资源以PDF格式存在&#xff0c;尤其是期刊论文、会议文章和学位论文。这些文档中蕴含丰富的结构化信息——如标题、作者、摘要、公式、表格等元数…

HY-MT1.5模型融合:与其他翻译引擎协作

HY-MT1.5模型融合&#xff1a;与其他翻译引擎协作 1. 引言 随着全球化进程的加速&#xff0c;跨语言沟通已成为企业、开发者乃至个人用户的刚需。尽管市面上已有多个成熟的商业翻译服务&#xff0c;但在特定场景下&#xff0c;如低延迟实时翻译、边缘设备部署或定制化术语处理…

STM32CubeMX下载安装过程中的权限问题图解说明

STM32CubeMX安装卡住&#xff1f;别让权限问题拖垮你的开发起点你有没有遇到过这种情况&#xff1a;好不容易从ST官网下载了STM32CubeMX的安装包&#xff0c;双击运行后进度条走到一半突然卡住、闪退&#xff0c;或者启动时报错“Failed to initialize Java Virtual Machine”&…

UART串口通信错误帧检测在工控行业的应用:操作指南

工业现场的“隐形守护者”&#xff1a;UART错误帧检测实战解析在自动化产线轰鸣运转的背后&#xff0c;无数设备正通过看似古老的串口默默对话。你是否曾遇到过这样的场景——某台传感器突然上报异常数据&#xff0c;PLC执行了未下发的指令&#xff0c;或是HMI界面频繁闪退&…

PDF-Extract-Kit常见误区:新手容易犯的错误

PDF-Extract-Kit常见误区&#xff1a;新手容易犯的错误 1. 引言 1.1 工具背景与使用现状 PDF-Extract-Kit 是由开发者“科哥”基于开源生态二次开发构建的一款PDF智能提取工具箱&#xff0c;集成了布局检测、公式识别、OCR文字提取、表格解析等核心功能。其WebUI界面简洁直观…

PDF-Extract-Kit代码实例:实现PDF公式检测与识别

PDF-Extract-Kit代码实例&#xff1a;实现PDF公式检测与识别 1. 引言&#xff1a;PDF智能提取的工程挑战与解决方案 在科研、教育和出版领域&#xff0c;PDF文档中包含大量结构化内容&#xff0c;如数学公式、表格和图文混排布局。传统OCR工具难以精准识别这些复杂元素&#…

PDF-Extract-Kit性能优化:异步处理与队列管理

PDF-Extract-Kit性能优化&#xff1a;异步处理与队列管理 1. 背景与挑战 PDF-Extract-Kit 是一个由开发者“科哥”二次开发构建的 PDF 智能提取工具箱&#xff0c;集成了布局检测、公式识别、OCR 文字识别、表格解析等核心功能。其基于 YOLO 模型、PaddleOCR 和深度学习技术&…