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++ 庫標頭檔案。 當翻譯單元包含相應的匯入宣告時,可匯入的 C++ 庫標頭檔案的內容就可用於該翻譯單元。 |
(C++20 起) |
匯入模組C++ 標準庫提供以下C++ 庫模組
對於標準庫中的每個宣告, |
(C++23 起) |
[編輯] 連結
C++ 標準庫中的實體具有外部連結。除非另有說明,物件和函式具有預設的 extern "C++" 連結。
從 C 標準庫中宣告的具有外部連結的名稱,其連結是 extern "C" 還是 extern "C++",是實現定義的。C++ 標準建議在這種情況下使用 extern "C++"。
在庫中定義並被 C++ 程式所需的物件和函式,在程式啟動前會被包含到程式中。
[編輯] 對標準庫實現的要求
[編輯] 保證
- 該標頭檔案的概要中,或
- 另一個頭檔案的概要中,而該標頭檔案似乎被包含在該標頭檔案的概要中。
對於在多個頭檔案中定義的型別和宏(如 NULL),以任何順序包含任意數量的這些標頭檔案都不會違反單一定義規則。
除非另有說明,所有由 C 標準庫定義的、展開為整型常量表達式的類物件宏都可以在 #if 預處理指令中使用。
呼叫一個標準庫非成員函式簽名總是會導致實際呼叫該函式。因此,一個符合標準的庫實現不能定義可能被一個有效的 C++ 程式呼叫的額外的非成員函式。
非成員函式簽名絕不會用額外的預設實參宣告。
除非另有說明,標準庫中的函式對非運算子、非成員函式的呼叫,不使用透過實參依賴查詢找到的來自其他名稱空間的函式。
對於類(模板)定義中的每個函式(模板)的友元宣告,不會為該函式(模板)提供其他宣告。
|
標準庫函式簽名只有在被要求為 constexpr 時才能宣告為 constexpr(libstdc++ cmath 在這方面是明顯不符合標準的)。如果一個頭檔案提供了 constexpr 函式或建構函式的任何非定義宣告,那麼相應的定義也應該在該標頭檔案中提供。 除非另有說明,每個標準庫函式應滿足以下每個要求以防止資料競爭:
|
(C++11 起) |
對於 C++ 標準庫中定義的每個要求從 C++ 標準庫中定義的另一個類派生的類,
- 如果基類被指定為 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++ 標準。
| 缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
|---|---|---|---|
| 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 | 如果一個頭檔案在不正確的位置 被包含,則需要診斷資訊 |
現在這種情況下 不需要診斷資訊 |