C++ 標準程式庫
C++ 標準程式庫提供了一系列廣泛的功能,可在標準 C++ 中使用。
目錄 |
[編輯] 類別
A 語言支援程式庫提供了 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 個元素的運算,在支援此類處理的平台上可能實作為平行運算。亂數元件提供生成偽亂數的功能。(C++11 起)
時間程式庫提供通用的時間工具。
輸入/輸出程式庫提供 iostream 元件,它們是 C++ 程式輸入和輸出的主要機制。它們可以與程式庫的其他元素一起使用,特別是字串、locale 和迭代器。
| (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 標頭。請參閱此處以瞭解說明。
除非另有說明,每個標頭 cxxx 的內容與 C 標準程式庫中指定的對應標頭 xxx.h 的內容相同。然而,在 C++ 標準程式庫中,宣告(C 中定義為巨集的名稱除外)位於命名空間 std 的命名空間範圍內。這些名稱(包括任何新增的重載)是否首先在全域命名空間範圍內宣告,然後透過明確的using 宣告注入到命名空間 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 標準 Annex K 名稱是否宣告在全域命名空間中(它們都沒有宣告在命名空間 std 中)是實作定義的。
[編輯] 使用程式庫
[編輯] 包含標頭
C++ 標準程式庫中的實體定義在標頭中,當翻譯單元包含適當的 #include 預處理器指令時,其內容將對該翻譯單元可用。
翻譯單元可以任意順序包含程式庫標頭。每個標頭可以被包含多次,其效果與只包含一次沒有不同,但包含 <cassert> 或 <assert.h> 的效果每次都取決於 NDEBUG 的詞法當前定義。
翻譯單元只能在任何宣告或定義之外,並且在該翻譯單元中首次引用該標頭中宣告的任何實體之前,詞法上包含標頭。不需要診斷。
| (自 C++20 起) |
匯入標頭C++ 程式庫標頭,或者對於獨立實作而言,由實作提供的這類標頭的子集,統稱為*可匯入的 C++ 程式庫標頭*。 可匯入的 C++ 程式庫標頭的內容,當翻譯單元包含適當的import 宣告時,將可供該翻譯單元使用。 |
(自 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++ 標準程式庫中指定的所有型別都是非最終型別。 |
(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++ 標準程式庫中的任何成員或非成員函式是否定義為行內函式,這一點未指定。
對於非虛擬的 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 | 如果標頭 包含在不正確的位置,則需要診斷 |
不需要診斷 在這種情況下 |