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

Effective C++ 條款 08:別讓異常逃離解構函式

     編輯:關於C++

核心規則

解構函式絕不應拋出異常。若解構函式拋出異常且未在內部捕獲,會導致程式終止(若在堆疊展開期間)或未定義行為(如標準容器銷毀元素時)。

為什麼危險?

class Widget {
public:
    ~Widget() { /* 可能拋出異常 */ }
};

void doSomething() {
    std::vector<Widget> v(10);
} // v 離開作用域,銷毀 10 個 Widget
// 若第 3 個 ~Widget() 拋出異常,前 2 個已銷毀,後 7 個不會被銷毀 → 資源洩漏
// 且異常傳播出 doSomething(),若此時正在堆疊展開(另一異常處理中)→ std::terminate()

情境:資源釋放可能失敗(如 DB 連線關閉)

class DBConnection {
public:
    static DBConnection create();
    void close(); // 失敗時拋出異常
};

// RAII 包裝
class DBConn {
    DBConnection db;
    bool closed = false;
public:
    ~DBConn() {
        if (!closed) {
            try { db.close(); }
            catch (...) { /* 記錄錯誤、吞下異常 */ }
        }
    }
    void close() { // 提供給使用者主動關閉
        db.close();
        closed = true;
    }
};

雙重保障策略

  1. 解構函式內部捕獲所有異常(catch(...)),記錄日誌後吞下,確保不拋出。
  2. 提供公開 close() 方法,讓使用者主動釋放資源並自行處理異常;解構函式僅作為安全網(若使用者忘記呼叫 close())。

設計原則

  • 資源管理類別應提供顯式釋放函式(如 close()、release())。
  • 解構函式呼叫釋放函式時,必須捕獲所有異常。
  • 若釋放失敗屬於「可預期錯誤」(如網路中斷),由使用者決定如何處理;解構函式只負責「不拋出異常」的底線保障。

總結

「解構函式不拋出異常」是 C++ 強異常安全的基石。採用RAII + 顯式釋放介面 + 解構函式吞下異常的模式,可同時滿足資源不洩漏與異常安全需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved