C++ 标准库
C++ 标准库提供了可在标准 C++ 中使用的各种工具。
目录 |
[编辑] 类别
语言支持库 提供了 C++ 语言某些部分所需的组件,例如内存分配 (new/delete) 和 异常处理。
(自 C++20 起) |
诊断库 为报告 C++ 程序中的错误提供了一致的框架,包括 预定义的异常类。
内存管理库 提供了用于内存管理的组件,包括 智能指针 和 作用域分配器(自 C++11 起)。
(自 C++11 起) |
通用工具库 包括其他库元素使用的组件,例如用于动态存储管理的 预定义存储分配器,以及用作 C++ 程序中基础结构的组件,例如 元组 和(自 C++11 起) 函数包装器。
容器、迭代器、范围(自 C++20 起) 和 算法 库为 C++ 程序提供对最广泛使用的算法和数据结构的子集的访问。
字符串库 提供对操作表示为以下类型同构序列的文本的支持: char、 char8_t(自 C++20 起)、 char16_t、 char32_t(自 C++11 起)、 wchar_t 以及任何其他类字符类型。
文本处理库 提供 正则表达式 匹配和搜索(自 C++11 起)、用于 文本格式化 的实用程序(自 C++20 起) 和 识别文本编码(自 C++26 起),以及 本地化工具。
数值库 提供 数值算法 和 复数 组件,以扩展对数值处理的支持。valarray 组件提供对 n-at-a-time 处理的支持,可能在支持此类处理的平台上实现为并行操作。 随机数组件 提供了生成伪随机数的工具。(自 C++11 起)
时间库 提供了通用的时间实用程序。
输入/输出库 提供了 iostream 组件,这些组件是 C++ 程序输入和输出的主要机制。它们可以与库的其他元素一起使用,特别是字符串、区域设置和迭代器。
(自 C++11 起) |
执行支持 库为管理通用执行资源上的异步执行提供了框架。 |
(自 C++26 起) |
[编辑] 库内容
C++ 标准库为 实体 和 宏 提供了定义,这些实体和宏在 C++ 标准库头文件 的概要中描述,除非另有说明。
除 operator new 和 operator delete 之外的所有库实体都在命名空间 std 或嵌套在命名空间 std 中的 命名空间 内定义(C 标准库工具的实体除外,请参见下文)。 在特定命名空间中声明的名称是直接在该命名空间中声明还是在该命名空间内的 内联命名空间 中声明是未指定的。(自 C++11 起)
[编辑] 头文件
C++ 标准库的每个元素都在头文件中声明或定义(视情况而定)。头文件不一定是源文件,并且头文件名称中由 <
和 >
分隔的序列不一定是有效的源文件名。
C++ 标准库提供C++ 库头文件和用于 C 库工具的附加 C++ 头文件(有关描述,请参见“头文件”页面)
用于 C 库工具的 C++ 头文件 | ||||
---|---|---|---|---|
<cassert> | <clocale> | <cstdarg> | <cstring> | |
<cctype> | <cmath> | <cstddef> | <ctime> | |
<cerrno> | <csetjmp> | <cstdio> | <cwchar> | |
<cfloat> | <csignal> | <cstdlib> | <cwctype> | |
<climits> | ||||
C++11 中添加的头文件 | ||||
<cfenv> | <cinttypes> | <cstdint> | <cuchar> | |
已移除的头文件 | ||||
<ccomplex> | (自 C++11 起)(在 C++17 中已弃用)(在 C++20 中已移除) | |||
<ciso646> | (在 C++20 中已移除) | |||
<cstdalign> | (自 C++11 起)(在 C++17 中已弃用)(在 C++20 中已移除) | |||
<cstdbool> | (自 C++11 起)(在 C++17 中已弃用)(在 C++20 中已移除) | |||
<ctgmath> | (自 C++11 起)(在 C++17 中已弃用)(在 C++20 中已移除) |
独立实现 具有实现定义的头文件集,有关头文件集的最低要求,请参见 此处。
[编辑] C 标准库
C++ 标准库还提供 C 标准库的工具,并进行了适当的调整以确保静态类型安全。许多库函数的描述都依赖于 C 标准库中这些函数的语义。
在某些情况下,标准 C++ 中指定的签名可能与 C 标准库中的签名不同,并且可能会声明其他重载,但行为和前提条件 (包括 C 的 restrict 所暗示的那些)(自 C++17 起) 是相同的,除非另有说明。
为了与 C 标准库兼容,C++ 标准库提供了下面列出的 C 头文件。这些头文件的预期用途仅用于互操作性。C++ 源文件可能需要包含其中一个头文件才能成为有效的 ISO C。不打算也成为有效 ISO C 的源文件不应使用任何 C 头文件。有关描述,请参见 此处。
C 头文件 | |||
---|---|---|---|
<assert.h> | <limits.h> | <stdarg.h> | <string.h> |
<ctype.h> | <locale.h> | <stddef.h> | <time.h> |
<errno.h> | <math.h> | <stdio.h> | <wchar.h> |
<float.h> | <setjmp.h> | <stdlib.h> | <wctype.h> |
<iso646.h> | <signal.h> | ||
C++11 中添加的头文件 | |||
<complex.h> | <inttypes.h> | <stdbool.h> | <tgmath.h> |
<fenv.h> | <stdalign.h> | <stdint.h> | <uchar.h> |
C++23 中添加的头文件 | |||
<stdatomic.h> | |||
C++26 中添加的头文件 | |||
<stdbit.h> | <stdchkint.h> |
除非另有说明,否则每个头文件 cxxx
的内容与 C 标准库 中指定的相应头文件 xxx.h
的内容相同。但是,在 C++ 标准库中,声明(在 C 中定义为宏的名称除外)位于命名空间 std 的命名空间范围内。未指定这些名称(包括添加的任何重载)是否首先在全局命名空间范围内声明,然后通过显式 using-declarations 注入到命名空间 std 中。
在 C 中定义为宏的名称(assert、offsetof、setjmp、va_arg、va_end 和 va_start)必须在 C++ 标准库中定义为宏,即使 C 允许实现为函数。
在 C 中定义为函数的名称必须在 C++ 标准库中定义为函数。这不允许 C 中允许的做法,即除了函数原型之外还提供屏蔽宏。在 C++ 中实现等效内联行为的唯一方法是提供作为 extern inline 函数 的定义。
在 C++ 中是关键字或运算符的标识符不能在 C++ 标准库头文件中定义为宏。特别是,包含标准头文件 <iso646.h> 无效。
[编辑] 与标准 C 中的安全函数关联的名称 (自 C++17 起)
如果包含任何 C++ 头文件,则是否在全局命名空间中声明以下任何 C 标准附件 K 名称是实现定义的(它们中没有一个在命名空间 std 中声明)
[编辑] 使用库
[编辑] 包含头文件
C++ 标准库中的实体在头文件中定义,当翻译单元包含适当的 #include 预处理指令时,这些头文件的内容可用于翻译单元。
翻译单元可以按任何顺序包含库头文件。每个头文件可以包含多次,其效果与仅包含一次的效果没有不同,但包含 <cassert> 或 <assert.h> 的效果每次都取决于 NDEBUG 的词法当前定义。
翻译单元只能在任何声明或定义之外包含头文件,并且在词法上在翻译单元中首次引用在该头文件中声明的任何实体之前。不需要诊断。
(自 C++20 起) |
导入头文件C++ 库头文件,或者,对于独立实现,实现提供的此类头文件的子集,统称为可导入的 C++ 库头文件。 当翻译单元包含适当的 import 声明 时,可导入的 C++ 库头文件的内容可用于翻译单元。 |
(自 C++20 起) |
导入模块C++ 标准库提供以下C++ 库模块
对于标准库中的每个声明, |
(自 C++23 起) |
[编辑] 链接
C++ 标准库中的实体具有 存储持续时间#外部链接。除非另有说明,否则对象和函数具有默认的 extern "C++" 链接。
从 C 标准库声明的具有外部链接的名称是否具有 extern "C" 或 extern "C++" 链接是实现定义的。C++ 标准建议在这种情况下使用 extern "C++"。
库中定义且 C++ 程序需要的对象和函数在程序启动之前包含在程序中。
[编辑] 标准库实现的 requirements
[编辑] 保证
C++ 头文件必须提供 声明 和 定义,这些声明和定义出现在
- 该头文件的概要中,或
- 另一个头文件的概要中,该概要似乎包含在该头文件的概要中。
对于在多个头文件中定义的类型和宏(例如 NULL),以任何顺序包含任意数量的这些头文件都不会违反 单一定义规则。
除非另有说明,否则 C 标准库定义的所有扩展为整数 常量表达式 的 类对象宏 都可以用于 #if
预处理指令中。
调用标准库非成员函数签名始终会导致实际调用该函数。因此,符合标准的库实现无法定义其他可能由有效 C++ 程序调用的非成员函数。
非成员函数签名永远不会使用其他 默认参数 声明。
除非另有说明,否则标准库中的函数对非运算符、非成员函数的调用不会使用通过 实参依赖查找 找到的来自另一个 命名空间 的函数。
对于类(模板)定义中函数(模板)的每个 友元声明,不为该函数(模板)提供其他声明。
仅当标准库函数签名需要为 constexpr 时,才能将其声明为 constexpr (libstdc++ cmath 在此处明显不符合标准)。如果头文件提供任何 constexpr 函数或构造函数的非定义声明,则还应在该头文件中提供相应的定义。 除非另有说明,否则每个标准库函数都应满足以下每个 requirements 以防止 数据竞争
|
(自 C++11 起) |
对于 C++ 标准库中定义的每个需要从 C++ 标准库中定义的另一个类 派生 的类,
- 如果基类指定为 virtual,则基类必须是 virtual 的,
- 如果基类未指定为 virtual,则基类不能是 virtual 的,并且
- 除非另有说明,否则具有不同名称的类型应为不同的类型。
除非另有说明,否则 C++ 标准库中指定的所有类型都是非 final 类型。 |
(自 C++11 起) |
如果 C++ 标准库中定义的函数指定在给定类型(在特定情况下)抛出 异常,则抛出的异常只能具有该类型或从该类型派生的类型,以便基类型的异常处理程序可以捕获它。
C 标准库中的函数仅当此类函数调用抛出异常的程序提供的函数时才能抛出异常(qsort() 和 bsearch() 符合此条件)。
C++ 标准库中定义的析构函数操作永远不会抛出异常。C++ 标准库中的每个析构函数的行为都好像它具有 非抛出异常规范。
如果 C++ 标准库中的函数通过 std::error_code 对象报告错误,则该对象的 category() 成员必须为源自操作系统的错误返回 std::system_category(),或者为源自其他位置的错误返回对实现定义的 std::error_category 对象的引用。应定义每个错误类别的 value() 的可能值。 C++ 标准库中定义的类型的对象可以 移动来源。移动操作可以显式指定或隐式生成。除非另有说明,否则此类移动来源的对象将放置在有效但未指定的状态。 C++ 标准库中定义的类型的对象可以 移动赋值 给自身。除非另有说明,否则此类赋值会将对象置于有效但未指定的状态。 |
(自 C++11 起) |
[编辑] 实现自由
C++ 标准库中的成员函数或非成员函数是否定义为 inline,标准未明确规定。
对于非 虚函数 C++ 标准库成员函数,可以声明一组不同的成员函数签名,前提是任何对该成员函数的调用,如果从给定的声明集中选择了一个重载,其行为都应如同选择了该重载。例如,这允许:
- 添加带有默认参数的形参,
- 用两个或多个行为等效的成员函数替换带有默认参数的成员函数,或
- 为成员函数名称添加额外的签名。
除非另有规定,否则 C++ 标准库中哪些函数可以递归重入是实现定义的。
如果对象对用户不可见且受到保护以防止数据竞争,C++ 标准库的实现可以在线程之间共享其自己的内部对象。 |
(自 C++11 起) |
C++ 标准库中的函数签名或类是否为 C++ 标准库中另一个类的友元,标准未明确规定。
此处描述的名称和全局函数签名由实现保留。
C++ 标准库中的任何类都可以派生自名称由实现保留的类。如果 C++ 标准库中定义的类需要从 C++ 标准库中的其他类派生,则该类可以直接从所需基类派生,也可以通过名称由实现保留的基类层次结构间接派生。
如果 C++ 标准库中定义的函数未明确规定抛出异常,但没有非抛出异常规范,则抛出的异常是实现定义的,但其类型应为 std::exception 或任何从 std::exception 派生的类型。
可以通过添加非抛出异常规范来加强非虚函数的异常规范。
[编辑] 注解
功能测试宏 | 值 | 标准 | 功能 |
---|---|---|---|
__cpp_lib_modules |
202207L |
(C++23) | 标准库模块 std 和 std.compat |
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
LWG 1 | C++98 | 来自以下内容的名称的语言链接 C 标准库未明确规定 |
它们是 实现定义的 |
LWG 119 | C++98 | 虚函数的异常规范 可以被加强 |
仅允许用于 非虚函数 |
LWG 147 | C++98 | 关于非成员的规范 函数仅考虑全局函数 |
也考虑 非全局函数 |
LWG 225 | C++98 | 标准库函数可能调用非成员函数 由于实参依赖查找而来自其他命名空间 |
禁止,除非 另有规定 |
LWG 336 | C++98 | <strstream> 不是 C++ 库头文件 | 它是 C++ 库头文件 |
LWG 343 | C++98 | 库头文件依赖关系未明确规定 | 已明确规定(在概要中列出) |
LWG 456 | C++98 | 用于 C 库设施的 C++ 头文件可以 仅在命名空间 std 中提供定义 |
允许在全局命名空间中定义 然后注入到命名空间 std 中 |
LWG 465 | C++98 | C++ 中作为关键字或运算符的标识符可以 在 C++ 标准库头文件中定义为宏 (仅 <ciso646> 要求不将它们定义为宏) |
所有 C++ 标准 库头文件不能 将它们定义为宏 |
LWG 1178 | C++98 | C++ 头文件必须包含 C++ 头文件 该头文件包含任何需要的定义 |
C++ 头文件必须提供声明 以及直接或 间接包含在其概要中的定义 |
LWG 2013 | C++11 | 标准未明确规定是否允许标准库将 标准未要求为 constexpr 的函数 声明为 constexpr |
禁止 |
LWG 2225 | C++98 | 如果在不正确的位置包含头文件,则需要诊断 是在不正确的位置包含头文件 |
在这种情况下,不需要诊断 在这种情况下需要诊断 |