第8章 标准库概览
如果只是临时露个小怯,
还费那劲学它干嘛呢?
—— 霍布斯虎
8.1 导言
任何重要的程序都不能单纯使用基本的编程语言。首先,要开发一套程序库。 这些库会构成后续工作的基石。 如果仅使用基本的编程语言编写,绝大多数程序都很烦冗, 相反,采用良好的程序库,几乎任何业务都能化繁为简。
继1-7章之后,9-15章对主要的标准库部件作了概览。
我很简略地介绍了实用的标准库类型,比如string
、ostream
、variant
、vector
、map
、path
、unique_ptr
、thread
、regex
和complex
,
及其基本用法。
像1-7章一样,对部分细节无法完全理解的时候,千万别分神、灰心。 本章的目的是:基本理解最实用的标准库部件。
标准库的内容占据了 ISO C++ 标准超过三分之二。 请浏览并尽量采用它,摒弃山寨货。 许多思想注入了它的设计当中,更多的则进入了实现, 还有许多劳作将投入到它的维护和扩展中去。
本书所描述的标准库部件,是每个完整C++实现的组成部分。 除这些标准库组件以外,多数实现还提供了 “图形用户接口(graphical user interface)”系统(GUIs)、 Web接口、数据库接口等等。 类似地,多数应用开发环境还为企业级或工业级“标准”的开发 和/或 运行环境提供了“基本库”。 在此,我不会讲述那些系统和库。
而旨在为标准定义下的C++提供一个自洽的描述,并确保示例可移植。 当然,也鼓励程序员去浏览各个系统提供的范畴广泛的基础部件。
8.2 标准库组件
标准库提供的基础部件可按此分类:
运行时语言支持(即:用于资源分配以及提供运行时类型信息)。
C 标准库(带有极细微的调整,以便降低与类型系统的冲突)。
字符串(对国际化字符集、本地化以及子字符串的只读检视提供支持);参见 §9.2。
对正则表达式匹配的支持;参见 §9.4。
I/O 流,是一个针对输入输出的可扩展框架,用户可添加自定义的类型、流、缓冲策略、 地区和字符集(第10章)。还有个文件系统库,以可移植方式操作文件(§10.10)。
容器(例如
vector
和map
)框架和算法 (例如find()
、sort)
和merge()
);参见第11章和第12章。 习惯上,该框架被称为 STL[Stepanov,1994],对用户而言是可扩展的, 可添加自定义容器和算法。对数值计算的支持(例如标准的数学函数、复数、带算术运算的向量和随机数生成器); 参见 §4.2.1 和第14章。
对并发运算的支持,包括
thread
和锁;参见第15章。 对并发的支持非常基础,因此用户能够以库的形式,为并发的新模型添加支持。多数STL算法以及部分数值算法的并行版本(即
sort()
和reduce()
); 参见 §12.9 和 §14.3.1。用于支持模板元编程的实用工具(即类型trait;§13.9), STL风格的泛型编程(即
pair
;§13.4.3),通用编程 (即variant
和optional
;§13.5.1,§13.5.2)和clock
(§13.7)。对高效且安全的通用资源管理提供支持,外加一个可选的垃圾回收器接口(§5.3)。
针对资源管理的“智能指针(smart pointers)” (即
unique_ptr
和shared_ptr
,§13.2.1)。特殊用途的容器,例如:
array
(§13.4.1)、bitset
(§13.4.2) 和tuple
(§13.4.3)。常见单位的后缀,例如:毫秒(millisecond)的
ms
和 虚部(imaginary)的i
(§15.4.4)。
某个类被纳入库中的判断标准是:
它能给几乎所有C++程序员(不论新手还是专家)带来益处,
相对于该部件的简单版本而言,通用版本不会显著增加负担,并且
基本用法应该易于学习(相较其功能固有的复杂性而言)。
基本上,C++标准库提供了最常见的基础数据结构,以及应用其上的基本算法。
8.3 标准库头文件和命名空间
每个标准库部件都通过某些头文件提供。例如:
这样就可以使用标准的string
和list
了。
标准库被定义在一个名为std
的命名空间(§3.4)里。
要使用标准库部件,可借助前缀std::
:
出于简洁的原因,本书极少像例中那样显式使用std::
,
也不总显式#include
必要的头文件。
要编译并运行这个代码片段,必须#include
对应的头文件并确保其声明的名称可访问。
例如:
一般来说,把某个命名空间里的所有名称一股脑丢进全局这种做法,颇有不妥。 但在此书专注于使用标准库,而熟知其涵盖的内容颇为有益。
以下是标准库头文件的一个精选,其中所有声明在命名空间std
里:
|精选标准库头文件||
-|-|-<algorithm>
|copy()
,find()
,sort()
|第12章<array>
|array
|§13.4.1<chrono>
|duration
,time_point
|§13.7<cmath>
|sqrt()
,pow()
|§14.2<complex>
|complex
,sqrt()
,pow()
|§14.2<filesystem>
|path
|§10.10<forward_list>
|forward_list
|§11.6<fstream>
|fstream
,ifstream
,ofstream
|§10.7<future>
|future
,promise
|§15.7<ios>
|hex
,dec
,secientific
,fixed
,defaultfloat
|§10.6<iostream>
|istream
,ostream
,cin
,cout
|第10章<map>
|map
,multimap
|§11.5<memory>
|unique_ptr
,shared_ptr
,allocator
|§13.2.1<random>
|default_random_engine
,normal_distribution
|§14.5<regex>
|regex
,smatch
|§9.4<string>
|string
,basic_string
|§9.2<set>
|set
,multiset
|§11.6<sstream>
|istringstream
,ostringstream
|§10.8
|精选标准库头文件(续)||
-|-|-<stdexcept>
|length_error
,out_of_range
,runtime_error
|§3.5.1<thread>
|thread
|§15.2<unordered_map>
|unordered_map
,unordered_multimap
|§11.5<utility>
|move()
,swap()
,pair
|第13章<variant>
|variant
|§13.5.1<vector>
|vector
|§11.2
此列表远称不上面面俱到。
C标准库的头文件,例如stdlib.h
也都在。
每个这样的头文件还有个改版,加了c
前缀,移除了.h
。
这样的版本,比如<cstdlib>
把它的声明都放进了命名空间std
。
8.4 忠告
[1] 别重复造轮子,用库;§8.1; [CG: SL.1]。
[2] 面临选择的时候,相较于其它的库,优先选标准库;§8.1; [CG: SL.2]。
[3] 别盲目觉得标准库通吃一切;§8.1。
[4] 针对使用的部件,记得
#include
其头文件;§8.3。[5] 记住,标准库部件定义在命名空间
std
里;§8.3; [CG: SL.3]。
最后更新于