8

库概述

如果只是临时露个小怯,

还费那劲学它干嘛呢?

—— 霍布斯虎1

8.1 导言

任何重要的程序都不能单纯使用基本的编程语言。首先,要开发一套程序库。 这些库会构成后续工作的基石。 如果仅使用基本的编程语言编写,绝大多数程序都很烦冗, 相反,采用良好的程序库,几乎任何业务都能化繁为简。

继1-7章之后,9-15章对主要的标准库部件作了概览。 我很简略地介绍了实用的标准库类型,比如stringostreamvariantvectormappathunique_ptrthreadregexcomplex, 及其基本用法。

像1-7章一样,对部分细节无法完全理解的时候,千万别分神、灰心。 本章的目的是:基本理解最实用的标准库部件。

标准库的内容占据了 ISO C++ 标准超过三分之二。 请浏览并尽量采用它,摒弃山寨货。 许多思想注入了它的设计当中,更多的则进入了实现, 还有许多劳作将投入到它的维护和扩展中去。

本书所描述的标准库部件,是每个完整C++实现的组成部分。 除这些标准库组件以外,多数实现还提供了 “图形用户接口(graphical user interface)”系统(GUIs)、 Web接口、数据库接口等等。 类似地,多数应用开发环境还为企业级或工业级“标准”的开发 和/或 运行环境提供了“基本库”。 在此,我不会讲述那些系统和库。

而旨在为标准定义下的C++提供一个自洽的描述,并确保示例可移植。 当然,也鼓励程序员去浏览各个系统提供的范畴广泛的基础部件。

8.2 标准库组件

标准库提供的基础部件可按此分类:

  • 运行时语言支持(即:用于资源分配以及提供运行时类型信息)。
  • C 标准库(带有极细微的调整,以便降低与类型系统的冲突)。
  • 字符串(对国际化字符集、本地化以及子字符串的只读检视提供支持);参见 §9.2。
  • 对正则表达式匹配的支持;参见 §9.4。
  • I/O 流,是一个针对输入输出的可扩展框架,用户可添加自定义的类型、流、缓冲策略、 地区和字符集(第10章)。还有个文件系统库,以可移植方式操作文件(§10.10)。
  • 容器(例如vectormap)框架和算法 (例如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),通用编程 (即variantoptional;§13.5.1,§13.5.2)和clock(§13.7)。
  • 对高效且安全的通用资源管理提供支持,外加一个可选的垃圾回收器接口(§5.3)。
  • 针对资源管理的“智能指针(smart pointers)” (即 unique_ptrshared_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 标准库头文件和命名空间

每个标准库部件都通过某些头文件提供。例如:

#include<string>
#include<list>

这样就可以使用标准的stringlist了。

标准库被定义在一个名为std的命名空间(§3.4)里。 要使用标准库部件,可借助前缀std::

std::string sheep {"Four legs Good; two legs Baaad!"};
std::list<std::string> slogans {"War is Peace", "Freedom is Slavery", "Ignorance is Strength"};

出于简洁的原因,本书极少像例中那样显式使用std::, 也不总显式#include必要的头文件。 要编译并运行这个代码片段,必须#include对应的头文件并确保其声明的名称可访问。 例如:

#include<string>        // make the standard string facilities accessible
using namespace std;    // make std names available without std:: prefix
string s {"C++ is a general−purpose programming language"}; // OK: string is std::string

一般来说,把某个命名空间里的所有名称一股脑丢进全局这种做法,颇有不妥。 但在此书专注于使用标准库,而熟知其涵盖的内容颇为有益。

以下是标准库头文件的一个精选,其中所有声明在命名空间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]。
1. 出自连环漫画集“The Complete Calvin and Hobbes”其中一册叫“Attack of the Deranged Mutant Killer Monster Snow Goons”,中文版为《卡尔文与霍布斯虎》系列丛书的第三册《变种雪怪杀手》,其中把此句译为“如果无知是瞬时的,为什么还要花时间学习呢?”,译者结合该小故事的上下文,认为该如此翻译。

results matching ""

    No results matching ""