当前位置: 首页 > news >正文

【C++初阶】STL 开篇:站在巨人肩膀上,先聊聊编码和现代语法

前言

在前面的博客中,我们系统学习了 类和对象(封装、继承、多态、构造/析构等),又深入探讨了 模板(函数模板、类模板、泛型编程基础)。从今天开始,我们将进入 C++ 标准库的核心领域——STL(Standard Template Library)。

1.STL

意义:可以说是C++的核心部分,它的存在让我们站在巨人的肩膀上,不必重复造轮子,你要的数组、链表、队列、排序、查找,标准库都帮你实现好了,性能顶尖,bug更少。用它,就是站在高手的肩膀上写代码。

2.编码表

意义:为下篇文章做准备,我们下篇将会探索第一个STL容器——string。在正式踏入string的世界之前,我们先聊一个看似基础却极其重要的话题——编码表(字符编码)。

3.C++11语法补充

现代C++能极大提高编程效率,这里仅先介绍两个现代C++的语法:auto关键字范围for,介绍的意义和编码表一样,为下篇string的引入做铺垫。

目录

前言

(一)STL简介

1.什么是STL

2.STL的版本

原始版本

P. J. 版本

RW版本

SGI版本

3.STL的六大组件

1.容器(Containers)

2.迭代器(Iterators)

3.算法(Algorithms)

4.仿函数(Functors)

5.适配器(Adapters)

6.分配器(Allocators)

组件间协作关系

4.STL的重要性

(二)编码表

1.为什么需要编码表

2.编码与 std::string 的关系

3.常见的编码方案

常见乱码场景对比

(三)C++11语法补充

1.auto关键字

背景

使用说明

代码演示

2.范围for

背景

使用说明

代码演示

本篇小结


(一)STL简介

1.什么是STL

STL是C++标准库的重要组成部分,不仅是一个可以复用的组件库,还是一个包罗数据结构和算法的软件框架。

2.STL的版本

原始版本

Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本--所有STL实现版本的始祖。

P. J. 版本

由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。

RW版本

由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。

SGI版本

由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。

STL要阅读部分源代码,主要参考的就是这个版本。

小故事:

HP版本的开源声明极具前瞻性:允许任何人使用、修改、商用,唯一条件是衍生品也必须开源。这影响了后来的很多开源协议。

SGI版本之所以可读性高,是因为它采用了完整命名(如 `__STL::vector`)和详细注释

面试中偶尔会问“你是否读过 STL 源码?”——哪怕只读过 `vector` 的扩容机制或 `sort` 的内省排序实现,都会是加分项。

3.STL的六大组件

STL(Standard Template Library)是C++标准库的核心部分,提供了一系列通用的模板类和函数,主要包括以下六大组件:

1.容器(Containers)

容器就是数据结构,用于存储和管理数据的模板类,分为序列容器和关联容器:

序列容器vector、list、string、array。

关联容器:set、multiset、map、multimap。

无序关联容器:unordered_set、unordered_map等(C++11引入)。

2.迭代器(Iterators)

提供访问容器元素的通用接口,分为五种类型:

输入迭代器(Input Iterator)

输出迭代器(Output Iterator)

前向迭代器(Forward Iterator)

双向迭代器(Bidirectional Iterator)

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

3.算法(Algorithms)

封装了常用操作,如排序、查找、遍历等,通过迭代器与容器交互。例如:

sort():排序。

find():查找元素。

swap() / reverse().............

4.仿函数(Functors)

5.适配器(Adapters)

对容器或迭代器的接口进行转换,例如:

容器适配器:stack、queue、priority_queue。

迭代器适配器:反向迭代器reverse_iterator。

6.分配器(Allocators)

管理内存分配与释放的模板类,默认使用std::allocator。用户可自定义以实现特殊内存管理需求。

组件间协作关系

容器通过分配器管理内存。

算法通过迭代器操作容器元素。

仿函数和适配器扩展算法和容器的功能。

4.STL的重要性

1. 极大提升开发效率

开箱即用的数据结构与算法:无需重复实现链表、动态数组、栈、队列、哈希表、排序、查找等常用组件,代码量显著减少。

2. 保证性能与正确性

高度优化:STL 由顶尖 C++ 专家实现,性能通常优于自己编写的“轮子”。

经过严格测试:减少因边界条件、内存管理等问题引入的 bug。

3. 统一编程接口,降低学习成本

迭代器统一访问:算法与容器通过迭代器解耦,学会一套迭代器操作即可用于所有容器。

4. 是现代 C++ 编程的事实标准

任何 C++ 工程(游戏、后端、嵌入式、高频交易等)几乎都会使用 STL。

面试与笔试中,STL 使用熟练度是考察 C++ 基础能力的重要指标。

5. 奠定泛型编程与数据抽象的基石

STL 完美展示了“泛型编程”的威力:算法与容器分离,通过模板和迭代器连接。

未来去互联网公司找工作或找实习时,一般都需要一轮笔试多轮面试,笔试和面试中都极易考察STL,毕竟STL是C++的核心。网上有句话说:“不懂STL,不要说你会C++”。STL是C++中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。


(二)编码表

1.为什么需要编码表

计算机只认识二进制,而人类需要处理文字、符号。编码表就是一套“翻译规则,把字符映射到数字,再转换为二进制存储或传输。

2.编码与 std::string 的关系

std::string 本身不关心编码——它只存储字节序列。这意味着你可以把任意编码的文本(如 UTF-8、GBK)放入 std::string,但如何解释这些字节(比如按字符遍历、获取字符数、大小写转换)需要你自己处理。

因此,s.size() 返回的是字节数,不是字符数;用下标修改字节可能破坏编码,造成乱码。

std::string 是 basic_string<char> 的别名。此外还有:

std::u16string(char16_t) → 通常用于 UTF-16 编码

std::u32string(char32_t) → 通常用于 UTF-32 编码

C++20 引入了 std::u8string(char8_t) → 专门用于 UTF-8 编码

但 std::string 始终不绑定任何编码,它只是一个字节容器。

类模板:basic_string

std::u16string和std::u32string分别是char16_t和char32_t的容器,通常用于存储UTF-16和UTF-32编码的文本。

3.常见的编码方案

ASCII:最基础的编码,用 7 位(后扩展为 8 位)表示英文字母、数字、标点。但它只能表示 128 个字符,连中文、日文等都无法处理。

GBK:中文环境下常用的多字节编码,用 1~2 个字节表示一个字符(英文 1 字节,中文 2 字节)。但不同国家和地区有各自的编码,容易产生乱码。

“GB”就是“国标”。

乱码:

void Test_String3() { string s1 = "引用"; s1[0]++; cout << s1 << endl; } int main() { Test_String3(); return 0; }

在 UTF-8 环境下,“引”的第一个字节被 +1,破坏了 UTF-8 序列,输出乱码。即使是在 GBK 环境下,也会因破坏双字节结构而导致乱码。

常见乱码场景对比

存储编码解释编码结果
GBKUTF-8乱码(如���
UTF-8GBK乱码(如浣犲ソ
UTF-8UTF-8正常

Unicode:统一所有字符的编码标准,为全世界每个字符分配唯一的码点(如 U+4F60 表示汉字“你”)。Unicode 只定义码点,不规定存储方式。

UTF-8:Unicode 的一种变长存储实现,英文占 1 字节,中文占 3 字节,兼容 ASCII,是目前互联网最通用的编码。


(三)C++11语法补充

1.auto关键字

背景

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量。

C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

使用说明

1.用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

2.当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

3.auto不能作为函数的参数,可以做返回值,但是建议谨慎使用

4.auto不能直接用来声明数组

代码演示

int i = 0; int& r1 = i; // r2不是int&引用,是int auto r2 = r1; //r3是int& 引用 auto& r3 = r1;

2.范围for

背景

对于一个又范围的集合而言,由程序员来说明循环的范围是很繁琐且多余的,有时候还会容易犯错。因此C++11引入了基于范围的for循环。

使用说明

1.for循环后的括号由冒号“:”分为两部分:冒号左边是范围内用于迭代的变量,冒号右边是被迭代的范围。 (自动取容器数据赋值,自动迭代++,自动判断结束)

2.支持迭代器的容器都可以使用范围for,且数组也支持(特殊处理)。

代码演示

//范围for 依次从容器里取值赋给ch,相当于拷贝一个临时变量 string str1("hello world"); for (char ch: str1) { cout << ch << " "; } cout << endl; //错误版本 string str1("hello world"); char ch; for (ch: str1) { cout << ch << " "; } cout << endl; //引用才能通过形参改变实参 for (auto& ch : str1) { ch--; } cout << str1 << endl;

本篇小结

本篇作为 STL 系列的开篇,从宏观上介绍了 STL 的诞生背景、六大组件及其重要性,帮助你建立起对 C++ 标准模板库的整体认知。同时,为了后续深入 std::string 的使用,我们补充了编码表的基础知识,澄清了 std::string 只存储字节、不关心编码这一关键点,并列举了常见乱码场景及成因。最后,简单介绍了 auto 和范围 for 这两项现代 C++ 语法,它们将在后续操作字符串时频繁出现。

从下一篇开始,我们将正式进入 std::string 的成员函数详解,包括构造、容量、迭代器、元素访问、修改器以及字符串查找等操作。掌握 string,是学好其他 STL 容器的第一步。

创作不易,如果你觉得本文有帮助,欢迎点赞、收藏、评论,你的支持是我继续分享的最大动力~ 我们下期见!

http://www.jsqmd.com/news/959349/

相关文章:

  • 入门大模型工程师第五课----通过微调改善大模型在垂直领域的表现
  • STM32CubeMX配置USART空闲中断+DMA接收不定长数据,5分钟搞定(HAL库版)
  • Speechless终极指南:3分钟学会微博备份,永久保存你的数字记忆
  • 保姆级教程:用ROS1在局域网内搞定两台机器人的主从通信(含rqt_graph可视化验证)
  • 基于小程序的医疗报销系统的设计与实现毕业设计源码
  • 别只看天梯图了!用这套“需求-预算”匹配法,5分钟搞定你的第一台游戏主机
  • 增强现实眼镜公司US Orange Inc聘请顾问为纳斯达克IPO做准备
  • 毕业季论文攻坚利器:百考通AI,一站式解决本硕博论文全流程难题
  • VS Code + Cursor + Continue + Warp + LangChain + Ollama —— 这套组合为何让资深工程师日均编码时长缩短2.8小时?
  • 2026市政领域诚信一体化废水处理设备推荐榜 - 优质品牌商家
  • 别再迷信软件了!用Python自己算筹码获利比(Winner函数),避免数据黑箱
  • 2026年热门的双臂机械手/三轴机械手推荐品牌厂家 - 行业平台推荐
  • SpringBoot项目升级Swagger3.0后,swagger-ui.html 404?别慌,一个注解和依赖就搞定
  • 从功能块到Case语句:手把手教你用CODESYS ST语言编写电机运动控制程序
  • 达州新高考志愿填报机构评测:四川老牌志愿填报机构哪家懂新高考/本土头部机构的硬核实力对比 - 优质品牌商家
  • UDS服务0x19到底做了什么?为什么一个ReadDTCInformation请求能把DEM全部串起来?
  • Meta:智能体自主发现高效混合架构
  • 从NLP到CV:手把手教你用PyTorch复现Vision Transformer(ViT)图像分类模型
  • 从零到一:手把手教你用Python复现GNSS-RTK/INS紧组合算法(附开源项目IGNAV实战)
  • 别再让同事乱Push了!手把手教你用GitLab分支保护,把CodeReview做在合并前
  • HoRain云--Claude Code 开发配置
  • 拓扑数据分析在天体物理预测中的应用
  • 告别打印插件!纯前端JS调用斑马打印机打印二维码的保姆级教程(附ZPL指令详解)
  • 宝塔面板一键部署的PHP自助建站源码,含多模板+自定义支付功能
  • Cesium for Unity终极指南:5分钟创建真实世界3D场景
  • 别再硬写样式了!用uni-app的midButton属性5分钟搞定中间凸起TabBar(H5/小程序通用)
  • 数据埋点与留存分析:核心链路的 DAU 观测实战
  • 2026年评价高的橡胶专用蜡/PVC专用蜡长期合作厂家推荐 - 行业平台推荐
  • 3D高斯泼溅技术与GaussianSwap人脸交换系统解析
  • GD32F103开发第一步:用标准外设库点亮LED,从环境搭建到代码烧录全流程