首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 異常處理完整指南:語法、機制、RAII、建構子/解構子陷阱與最佳實踐

     編輯:關於C++

異常是 C++ 標準化的錯誤處理機制,解決了返回值可被忽略、errno 執行緒不安全、setjmp/longjmp 不呼叫解構子等歷史痛點。本文系統涵蓋語法規則、堆疊展開機制、RTTI 動態匹配、std::exception 體系、RAII 資源管理、建構子/解構子異常安全、noexcept 規格與實戰決策指南。

核心語法速查

try {
    // 可能拋出異常的代碼
} catch (const MyException& e) { // 捕獲特定型別(引用避免切割)
    // 處理
} catch (...) { // 捕獲所有其他異常
    // 記錄日誌、轉換型別後重拋
    throw; // 重拋當前異常
}

// 函數異常規格 (C++11 棄用動態規格,改用 noexcept)
void func() noexcept;          // 承諾不拋出
void func2() noexcept(false);  // 可能拋出 (預設)

異常運作機制:堆疊展開

  1. throw expr 建立異常物件(複製/移動至編譯器保留緩衝區)。
  2. 沿呼叫鏈向上尋找匹配的 catch,沿途**銷毀所有區域物件**(呼叫解構子),此過程稱「堆疊展開」。
  3. 若無匹配 catch → 呼叫 std::terminate → std::abort 終止程式。
  4. 匹配規則:依 catch 出現順序,**第一個型別相容**者勝出(支援繼承多型、... 兜底)。

RAII:資源獲取即初始化

區域物件在堆疊展開時自動解構,是唯一可靠的資源釋放機制。

void foo() {
    std::unique_ptr p(new Resource); // 或 std::lock_guard lk(mtx);
    bar(p.get()); // 若 bar 拋出異常,p 自動釋放 Resource
}
// 無需手寫 try/catch/finally

建構子與解構子的異常安全

場景規則對策
建構子拋出**不會呼叫該物件解構子**,但**已完成建構的成員/基類解構子會被呼叫**成員改用 RAII 智慧指標 (unique_ptr, vector) 自動管理
解構子拋出**嚴禁**;若解構子期間再拋出異常 → std::terminate解構子內部 try/catch 吞噬或轉換為錯誤碼/日誌
建構子資源洩漏new char[10]; throw; 導致記憶體洩漏auto_ptr p(new char[10]); (C++11 用 unique_ptr)

何時使用異常 vs 返回值 vs 斷言

  • 異常:違反前置條件、資源耗盡、不可預期的執行時錯誤(檔案不存在、網路中斷)。
  • 返回值/錯誤碼:可預期的正常分支(查無資料、驗證失敗、使用者取消)。
  • 斷言 assert:僅用於**程式邏輯錯誤**(前置條件違反、不可達程式點),Release 版移除,不可用於處理執行時錯誤。

實戰範例:集中資源清理

void process() {
    Resource* r1 = nullptr, *r2 = nullptr, *r3 = nullptr;
    try {
        r1 = acquire1(); step1(r1);
        r2 = acquire2(); step2(r2);
        r3 = acquire3(); step3(r3);
    } catch (...) {
        release(r1); release(r2); release(r3); // 集中釋放
        throw; // 保持異常傳播
    }
}
// 對比:無異常版需在每個 if (!step) 重複釋放代碼
「異常不是控制流工具,是『失敗時的安全網』。善用 RAII 讓資源管理隱形,讓業務邏輯專注於成功路徑。」
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved