C++中的STL与标准库算法
By FunnyAWM运行环境说明本章及以后章节换用Windows 64位x86 MinGW GCC编译器进行编译及运行。在C中我们有一组绝大部分编译器都共有的文件这些文件被称作标准库。其中STL也在标准库的范围内。这一章我们来具体探讨一下C中的STL标准模板库容器与标准库函数。在这个仓库中可以找到大量对本章知识的应用。其中大部分容器出于Qt的限制改为了使用Qt提供的容器版本与标准STL容器可能有部分不同STL容器可能缺失了部分方法仅供参考。1. STL容器1. 有哪些容器STL中包含的常用容器有string、vector、map、unordered_map等。受限于文章篇幅我们在这一章里只重点讲述string与vector容器其他容器可能会有提及。2. stringC的字符串容器string容器应该是我们最常用的STL容器之一。string容器可以通过使用C字符串、复制、移动、使用有参构造函数等进行初始化。其中类提供的特殊有参构造函数如下函数描述string(size_type n, char c)创建一个包含n个元素的string对象其中每一个元素都被初始化为字符ctemplateclass Iter string(Iter begin, Iter end)从迭代器范围创建string对象string(const string str, string size_type pos 0, size_type n npos)创建string对象数据为从pos位置开始的n个字符如果n没有指定则为到结尾string(initializer_listchar il)根据初始化列表创建对象将在后面详细讲述容器初始化列表我们可以直接使用cin或getline函数来向string对象中输入数据。string对象的长度是可变的在对象空间不足时会自动扩容。例如std::string str1;std::cinstr1;std::getline(std::cin,str1);// 这种方式同样可以用于从文件流构造字符串getline函数的第一个参数是一个istream流它可以从用户键盘或文件中读取数据并初始化对应的对象。我们将在后续章节详细讲解C的IO流。由于string类重载了[]运算符它也可以被当做常规的C字符串被访问。string类提供了很多功能包括查找子串、获取字符串长度、删除或替换字符等。STL类中的所有函数都能够在Cpp Reference找到在这里不再赘述。3. vectorC的可变长数组与string类似vector也具有可变长度特性。vector属于我们之前提到的泛型类它接受一个任意类型的模板参数然后根据模板类型来初始化对象。vector同样为我们提供了很多功能包括获取元素数目、交换容器内容、获取容器的迭代器等。这里我们不再赘述其他方法重点讲述一下STL容器中迭代器的概念。4. 迭代器迭代器可以被当做指向容器元素的指针使用但其并不指向任何实际对象常用于遍历整个容器。例如voidMSTDataSource::updateFavoriteBatch(constQListFavoriteUpdateupdates){query.exec(BEGIN TRANSACTION);for(autoupdateupdates.begin();update!updates.end();update){prepareStatement(UPDATE musicInfo SET favorite :fav WHERE fileName :fileName);bindValue(:fav,update-isFavorite);bindValue(:fileName,update-fileName);execQuery();}query.exec(COMMIT);}当然由于QList具有迭代器与可迭代特性上述代码也可以用C的范围for循环进一步简化voidMSTDataSource::updateFavoriteBatch(constQListFavoriteUpdateupdates){query.exec(BEGIN TRANSACTION);for(constautoupdate:updates){prepareStatement(UPDATE musicInfo SET favorite :fav WHERE fileName :fileName);bindValue(:fav,update.isFavorite);bindValue(:fileName,update.fileName);execQuery();}query.exec(COMMIT);}几乎所有具有迭代器的容器也都支持反向迭代操作。要实现反向迭代只需要将begin()与end()改为rbegin()与rend()即可。end()迭代器指向的对象都是容器中最后一个对象的后一对象。所有涉及到双迭代器的操作后续用it1代表靠前的迭代器用it2代表靠后的其包含的范围都是[it1, it2)包括it1指向的元素但不包含it2指向的元素。迭代器有以下几个不同的类型输入迭代器只读迭代器单向移动只能遍历一次适用于从文件或输入流中读取数据输出迭代器只写迭代器单向移动只能遍历一次适用于将数据输出到文件或输出流中前向迭代器结合了前两种迭代器的特点同时支持了多次遍历双向迭代器在前向迭代器的基础上实现了双向移动随机访问迭代器在双向迭代器的基础上加入了任意位置跳转的能力。随机访问迭代器支持常数时间的任意位置跳转O ( 1 ) O(1)O(1)而其他迭代器只能通过逐步移动来访问元素从当前位置移动到任意位置的时间复杂度为O ( n ) O(n)O(n)。时间复杂度描述了某个算法或操作需要耗费的时间随输入规模的变化趋势。其中O ( 1 ) O(1)O(1)代表该算法或操作在使用任意参数时耗费的时间恒定而O ( n ) O(n)O(n)代表该算法或操作需要的时间随需要进行该操作的元素数量呈线性增长。相似的表述还有O ( n 2 ) O(n^2)O(n2)需要的时间随元素数呈二次增长、O ( l o g n ) O(log n)O(logn)需要的时间随元素数呈对数增长、O ( n l o g n ) O(n log n)O(nlogn)需要的时间随元素数呈线性对数增长、O ( 2 n ) O(2^n)O(2n)需要的时间随元素数呈指数增长、O ( n ! ) O(n!)O(n!)需要的时间随元素数呈阶乘增长等。注意1当容器发生结构性变化例如vector扩容、deque插入中间元素时针对当前容器的迭代器将全部失效需要重新为其赋值。使用失效的迭代器可能会引起未定义行为。2. 标准库算法标准库算法为我们提供了一系列方便的功能包括以下几方面非修改式序列操作例如for_each()与find()等修改式序列操作例如transform()、random_shuffle()、any_of()、remove_if()等排序、交换等及其相关操作例如sort()与swap()等通用数字运算。这些函数主要集中在algorithm头文件一些基础数学运算函数则在numeric头文件中。以下我们选取几个典型函数进行详细讲解所有函数的使用方法都能够在Cpp Reference找到。any_of与remove_if函数于C11中被实现而random_shuffle函数已在C17中被移除在C11及以后更推荐使用std::shuffle。1. for_each该函数接收两个迭代器参数与一个函数指针或Lambda表达式对迭代器范围内的所有对象执行函数或Lambda操作。2. xxx_of宇宙与xxx_if宇宙这些函数都是从C11开始引入的算法极大方便了对容器的元素筛选与整体判断操作。any_of函数接收两个迭代器参数与一个函数指针或Lambda表达式用于判断迭代器范围中是否有元素满足函数或Lambda表达式中描述的条件。其中函数指针或Lambda表达式必须满足谓词要求即要求这个函数的返回类型必须为bool。all_of对参数的要求同any_of用于判断迭代器范围中是否所有元素都满足要求。none_of对参数的要求同any_of用于判断迭代器范围中是否没有元素满足要求。以上所有函数在满足判断时返回true不满足时返回false。remove_if函数对参数的要求同any_of但是remove_if的作用为将所有不满足函数或Lambda表达式中描述的条件的元素移动到容器尾并返回一个新范围结尾的尾迭代器。这个函数配合erase函数可以用于快速筛选满足指定要求的值被称为擦除移除手法。例如std::string strThe quick brown fox jumps over the lazy dog;str.erase(std::remove_if(str.begin(),str.end(),[](unsignedcharch){returnstd::isspace(ch);// 需要包含cctype以使用isspace函数}),str.end());// 这个操作移除了容器中的所有空格字符从C20开始这个操作也可以被直接被erase_if替代直接实现移除擦除手法一步到位。3. 排序与交换1. 排序sort函数为我们提供了标准库内部支持的排序操作对于可比较类型直接调用sort函数即可。对于自定义类型通常需要手动实现operator以满足可比较特性或手动传入返回bool类型的比较函数以满足可比较特性。如果没有实现可比较特性编译器会在编译时抛出如下报错// 示例代码#includelistusingnamespacestd;structMyStruct{inta;};intmain(){std::listMyStructlist;list.sort();// 这里使用的是list容器的sort成员函数而非std::sort这是因为list无法满足标准sort函数的随机访问迭代器要求list只有双向迭代器}In file included from E:/JetBrainsTools/CLion/bin/mingw/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c/list:65, from C:/Users/11429/CLionProjects/toturial/main.cpp:2: E:/JetBrainsTools/CLion/bin/mingw/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c/bits/stl_list.h: In instantiation of bool std::__detail::_Scratch_list::_Ptr_cmp_Iter, void::operator()(std::__detail::_List_node_base*, std::__detail::_List_node_base*) const [with _Iter std::_List_iteratorMyStruct]: E:/JetBrainsTools/CLion/bin/mingw/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c/bits/stl_list.h:203:18: required from void std::__detail::_Scratch_list::merge(std::__detail::_List_node_base, _Cmp) [with _Cmp _Ptr_cmpstd::_List_iteratorMyStruct, void] E:/JetBrainsTools/CLion/bin/mingw/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c/bits/list.tcc:515:23: required from void std::__cxx11::list_Tp, _Alloc::sort() [with _Tp MyStruct; _Alloc std::allocatorMyStruct] C:/Users/11429/CLionProjects/toturial/main.cpp:11:14: required from here E:/JetBrainsTools/CLion/bin/mingw/lib/gcc/x86_64-w64-mingw32/13.1.0/include/c/bits/stl_list.h:188:34: error: no match for operator (operand types are MyStruct and MyStruct) 188 | { return *_Iter(__lhs) *_Iter(__rhs); } | ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~这里的报错原因是由于我们既没有实现operator也没有实现自定义比较函数sort函数由于无法建立严格弱序关系而报错。DLC从离散数学角度解释排序为什么要实现正确比较STL的排序算法要求元素上存在一种严格弱序关系从数学上讲这要求operator函数或自定义比较函数必须定义该集合上的一个二元关系R ( a b ) R(a b)R(ab)。STL要求这样的R必须满足以下三条公理非自反性Irreflexive对于集合中的任意元素a aa,a a a aaa恒为假。即任何元素都不能小于自身;非对称性Asymmetric对于任意元素a , b a, ba,b如果a b abab为真那么b a baba必然为假。不能出现“相互小于”这种左右脑互搏的情况。传递性Transitive对于任意元素a , b , c a,b,ca,b,c如果a b abab且b c bcbc那么a c acac必然为真。如果其中的任意一条公理无法满足就会导致该R在集合上的关系不再是一个偏序关系。这将导致排序算法无法保证满足其不变式进而导致算法结果不可预测。假设我们有以下代码#includeiostream#includevector#includealgorithmstructBroken{intvalue;};intmain(){autobroken_compare[](constBrokena,constBrokenb){if(a.value%20b.value%21)returntrue;if(a.value%21b.value%20)returnfalse;returna.valueb.value;};std::vectorBrokenvec{{2},{3},{5},{1},{4}};std::sort(vec.begin(),vec.end(),broken_compare);// 结果不可预测可能死循环或错误排序for(constautox:vec){std::coutx.value ;}return0;}很明显上述代码中的broken_compare函数不满足偏序关系中要求的传递性进而导致sort函数的结果不可预测甚至导致未定义行为。2. 交换swap函数能够实现对任意相同类型变量的值交换操作这要求元素必须实现可复制特性即有能够使用的复制构造函数即便它是默认的。从C11开始swap函数会优先使用移动构造函数实现交换行为如移动构造函数不可用则会退化到复制行为。对于STL容器部分容器实现了自己的swap成员函数用于快速交换整个容器而不需要逐个交换元素。

相关新闻

CUE: Concept-Aware Multi-Label Expansion to Mitigate Concept Confusion in Long-Tailed Learning

CUE: Concept-Aware Multi-Label Expansion to Mitigate Concept Confusion in Long-Tailed Learning

CUE:面向长尾学习中概念混淆问题的概念感知多标签扩展方法,主要解决基础模型在长尾学习微调过程中出现的概念混淆问题,本文中还指出在使用 CLIP 等基础模型进行长尾微调时,模型不仅会受到类别不均衡的影响,还会破坏原有…

2026/7/4 19:55:27阅读更多 →
独立开发实战:学生管理+考试防作弊机制设计

独立开发实战:学生管理+考试防作弊机制设计

独立开发实战:学生管理 考试防作弊机制设计 一、问题起源 在上一篇我分享了在线考试系统的整体搭建过程。但在实际使用中,老师和学生都反馈了一些问题: 老师反馈: 「学生关了浏览器,后台还显示在作答,这…

2026/7/4 19:55:27阅读更多 →
终极指南:40+经典DSGE模型库如何加速你的宏观经济研究

终极指南:40+经典DSGE模型库如何加速你的宏观经济研究

终极指南:40经典DSGE模型库如何加速你的宏观经济研究 【免费下载链接】DSGE_mod A collection of Dynare models 项目地址: https://gitcode.com/gh_mirrors/ds/DSGE_mod 你是否曾在经济学研究中为复现经典模型而苦恼?是否想验证理论结果却被技术…

2026/7/4 19:55:27阅读更多 →
DeployQt:告别繁琐部署,三步搞定Qt应用打包分发终极指南

DeployQt:告别繁琐部署,三步搞定Qt应用打包分发终极指南

DeployQt:告别繁琐部署,三步搞定Qt应用打包分发终极指南 【免费下载链接】DeployQt 基于Windows系统的Qt打包程序(最新版本V1.0.1) 项目地址: https://gitcode.com/gh_mirrors/de/DeployQt 还在为Qt应用部署而头疼吗?每次发布都要手动…

2026/7/4 21:00:46阅读更多 →
国产大模型2024实测指南:文心一言、通义千问、Kimi等6大平台对比

国产大模型2024实测指南:文心一言、通义千问、Kimi等6大平台对比

我不能按照该标题生成相关内容。原因如下:标题中提及的“GPT-5”目前(截至2024年中)并不存在。OpenAI官方从未发布、命名或确认GPT-5模型,亦无任何公开技术文档、API接口、模型权重或权威渠道证实其存在。所有声称“可使用GPT-5”…

2026/7/4 21:00:46阅读更多 →
如何系统提升AI编程质量:基于Karpathy原则的3个关键策略

如何系统提升AI编程质量:基于Karpathy原则的3个关键策略

如何系统提升AI编程质量:基于Karpathy原则的3个关键策略 【免费下载链接】andrej-karpathy-skills A single CLAUDE.md file to improve Claude Code behavior, derived from Andrej Karpathys observations on LLM coding pitfalls. 项目地址: https://gitcode.c…

2026/7/4 21:00:46阅读更多 →
终极Mac清理指南:5分钟学会用Mole命令行工具释放存储空间

终极Mac清理指南:5分钟学会用Mole命令行工具释放存储空间

终极Mac清理指南:5分钟学会用Mole命令行工具释放存储空间 【免费下载链接】Mole 🐹 Clean, uninstall, analyze, optimize, and monitor your Mac from the terminal. 项目地址: https://gitcode.com/GitHub_Trending/mole15/Mole 还在为Mac存储空…

2026/7/4 21:00:46阅读更多 →
N_m3u8DL-RE:跨平台流媒体下载工具的终极指南

N_m3u8DL-RE:跨平台流媒体下载工具的终极指南

N_m3u8DL-RE:跨平台流媒体下载工具的终极指南 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE N_m3u…

2026/7/4 21:00:46阅读更多 →
关注点之(五)大畸变pinhole/fisheye场景的重建及渲染

关注点之(五)大畸变pinhole/fisheye场景的重建及渲染

0.概述 对较大的畸变场景重建及渲染,若先将鱼眼图像 “去畸变” 为针孔图像,会裁剪边缘区域,丢失大量场景信息(鱼眼图像边缘信息密度高,对深度估计至关重要,这种方式不可取,且无法与后续重建流程端到端优化,导致最终重建误差无法最小化。对于fisheye-gs这种做法采用对…

2026/7/4 20:55:46阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/4 14:25:39阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/4 14:57:00阅读更多 →
端到端自动驾驶:从GTC‘26看工程可信落地的核心逻辑

端到端自动驾驶:从GTC‘26看工程可信落地的核心逻辑

1. 项目概述:当算法工程师走进GTC26展厅,看到的不是芯片,而是“端到端”的呼吸节奏“端到端”这三个字,在GTC’26现场出现的频率,高得像NVLink带宽测试时的峰值曲线——它不再是一个论文里的技术路径选项,而…

2026/7/4 0:02:48阅读更多 →
缺牙修复科普:常见义齿类型与选择参考

缺牙修复科普:常见义齿类型与选择参考

缺牙修复科普:常见义齿类型与选择参考牙齿缺失是中老年人群中较为常见的口腔问题,不仅会造成咀嚼不便、进食受影响,长期还可能对营养摄入与日常社交带来困扰。义齿是改善缺牙问题的常用方式,目前市面上的义齿种类较多,…

2026/7/4 0:02:48阅读更多 →
STM32F091RC与LTC6904实现高精度方波信号生成

STM32F091RC与LTC6904实现高精度方波信号生成

1. 项目概述:LTC6904与STM32F091RC的精准方波生成方案在嵌入式系统开发中,精确的时钟信号和定时控制往往是项目成败的关键。LTC6904作为一款低功耗、高精度的可编程振荡器芯片,与STM32F091RC这款ARM Cortex-M0内核微控制器的组合,…

2026/7/4 0:02:48阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/4 1:16:56阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/4 2:33:55阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/4 2:33:55阅读更多 →