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

Effective C++ 條款 08:析構函數絕不讓異常逃逸

     編輯:關於C++

為什麼危險?

析構函數若拋出異常,在堆疊展開期間若再有另一異常被拋出,程序會直接調用 std::terminate 終止。標準庫容器(如 vector<Widget>)銷毀元素時,若某元素析構拋出異常,其餘元素將不再被析構,導致資源洩漏或狀態不一致。

錯誤示範

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

void doSomething() {
    vector v(10);
    // v 析構時逐個銷毀 Widget,若第 3 個拋出異常,第 4~10 個不再析構
}

兩種補救策略

策略一:吞噬異常並記錄

~DBConn() {
    try { db.close(); }
    catch (...) {
        logError("DBConn::close failed");
        // 吞下異常,不傳播
    }
}

策略二:遇異常即終止程序

~DBConn() {
    try { db.close(); }
    catch (...) {
        logError("DBConn::close failed");
        std::abort(); // 立即終止
    }
}

最佳實踐:重新設計介面

提供顯式 close() 函數供客戶端調用,析構函數僅作保底:

class DBConn {
public:
    void close() { /* 可能拋出,客戶端決定如何處理 */ }
    ~DBConn() {
        if (!closed) {
            try { close(); }
            catch (...) { std::abort(); } // 保底
        }
    }
private:
    bool closed = false;
    DBConnection db;
};

關鍵提醒

析構函數絕對不要吐出異常;若調用的函數可能拋出,應捕獲並吞下或終止程序。
若客戶需對操作失敗做出反應,類別應提供普通函數(非析構函數)執行該操作。

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