命名空間
變體
動作

例外

出自 cppreference.com
< cpp‎ | language
 
 
C++ 語言
一般主題
流程控制
條件執行陳述式
if
疊代陳述式 (迴圈)
for
範圍 for (C++11)
跳躍陳述式
函式
函式宣告
Lambda 函式運算式
inline 指定符
動態例外規範 (直到 C++17*)
noexcept 指定符 (C++11)
例外
命名空間
型別
指定符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
儲存期指定符
初始化
 
例外
try 區塊
拋出例外
處理例外
例外規格
    noexcept 規格 (C++11)
    動態規格 (C++17 前*)
noexcept 運算子 (C++11)
 

例外處理提供了一種將控制權與資訊從程式執行過程中的某一點,轉移至先前執行路徑上相關聯之處理器的方法(換句話說,例外處理會沿著呼叫堆疊向上傳遞控制權)。

求值一個 throw 表達式將會拋出一個例外。例外也可以在其他環境中拋出。

為了捕捉例外,throw 表達式必須位於 try 區塊內,且該 try 區塊必須包含一個與該例外物件類型相符的處理器

宣告函式時,可以提供下列規格來限制函式可能拋出的例外類型:

(直到 C++17)
(C++11 起)

例外處理期間產生的錯誤由 std::terminate std::unexpected(C++17 前) 處理。

目錄

[編輯] 用法

雖然 throw 表達式可用於將控制權轉移至執行堆疊上任意區塊的程式碼(類似 std::longjmp),但其預期的用途是錯誤處理。

[編輯] 錯誤處理

拋出例外用於標示函式發生的錯誤,此處的「錯誤」通常僅限於下列情況[1][2][3]

  1. 未能滿足後置條件,例如無法產生有效的回傳值物件。
  2. 未能滿足必須呼叫的另一個函式之前置條件。
  3. (針對非私有成員函式)未能(重新)建立類別的不變量(class invariant)。

特別地,這意味著建構子(另見 RAII)與大多數運算子的失敗應該透過拋出例外來報告。

此外,所謂的「寬合約」(wide contract)函式會使用例外來指出不可接受的輸入。例如,std::basic_string::at 沒有前置條件,但會透過拋出例外來指出索引超出範圍。

[編輯] 例外安全性

當函式報告錯誤狀況後,程式的狀態可能會提供額外的保證。通常公認有以下四種例外保證等級[4][5][6],它們彼此之間是嚴格的超集關係:

  1. 無拋出(或無失敗)例外保證 (Nothrow/Nofail guarantee) — 函式永遠不會拋出例外。解構子及其他在堆疊展開期間可能被呼叫的函式,預期應具備無拋出特性(錯誤透過其他方式報告或隱藏)。解構子預設為 noexcept(C++11 起) 無失敗(函式總是成功)預期應用於 swap、移動建構子,以及其他被提供強例外保證之函式所使用的函式。
  2. 強例外保證 (Strong exception guarantee) — 若函式拋出例外,程式狀態會回滾至函式呼叫前的狀態(例如 std::vector::push_back)。
  3. 基本例外保證 (Basic exception guarantee) — 若函式拋出例外,程式處於有效狀態。不會發生資源洩漏,且所有物件的不變量皆維持完整。
  4. 無例外保證 (No exception guarantee) — 若函式拋出例外,程式可能處於無效狀態:可能已發生資源洩漏、記憶體損毀,或其他破壞不變量的錯誤。

通用元件(Generic components)可能還提供例外中立保證 (exception-neutral guarantee):若例外從範本參數拋出(例如從 std::sortCompare 函式物件,或 std::make_sharedT 的建構子拋出),該例外將原封不動地傳播給呼叫者。

[編輯] 例外物件

雖然任何完整類型的物件及指向 void 的 cv 限定指標皆可作為例外物件拋出,但所有標準程式庫函式皆透過值拋出未命名的物件,且這些物件的類型(直接或間接)衍生自 std::exception。使用者定義的例外通常也遵循此模式。[7][8][9]

為了避免不必要的例外物件複製以及物件切割(object slicing),處理器的最佳做法是以參考方式捕捉。[10][11][12][13]

[編輯] 附註

特性測試巨集 數值 標準 功能
__cpp_constexpr_exceptions 202411L (C++26) constexpr 例外

[編輯] 外部連結

  1. H. Sutter (2004) "When and How to Use Exceptions" 於 Dr. Dobb's
  2. H. Sutter, A. Alexandrescu (2004), "C++ Coding Standards", 項目 70
  3. C++ Core Guidelines I.10: Use exceptions to signal a failure to perform a required task
  4. B. Stroustrup (2000), "The C++ Programming Language" 附錄 E
  5. H. Sutter (2000) "Exceptional C++"
  6. D. Abrahams (2001) "Exception Safety in Generic Components"
  7. D. Abrahams (2001) "Error and Exception Handling"
  8. isocpp.org Super-FAQ "What should I throw?"
  9. C++ Core Guidelines E.14: Use purpose-designed user-defined types as exceptions (not built-in types)
  10. C++ Core Guidelines E.15: Throw by value, catch exceptions from a hierarchy by reference
  11. S. Meyers (1996) "More Effective C++" 項目 13
  12. isocpp.org Super-FAQ "What should I catch?"
  13. H. Sutter, A. Alexandrescu (2004) "C++ Coding Standards" 項目 73
English Deutsch 日本語 中文(简体) 中文(繁體)