C++箴言:防止異常離開析構(gòu)函數(shù)

字號(hào):

C++ 并不禁止從析構(gòu)函數(shù)中引發(fā)異常,但是這確實(shí)妨礙了實(shí)踐。至于有什么好的理由,考慮:
    class Widget {
    public:
     ...
     ~Widget() { ... } // assume this might emit an exception
    };
    void doSomething()
    {
    std::vector v;
    ...
    } // v is automatically destroyed here
    當(dāng) vector v 被析構(gòu)時(shí),它有責(zé)任銷毀它包含的所有 Widgets。假設(shè) v 中有十個(gè) Widgets,在銷毀第一個(gè)的時(shí)候,拋出一個(gè)異常。其他 9個(gè) Widgets 仍然必須被銷毀(否則他們持有的任何資源將被泄漏),所以 v 應(yīng)該調(diào)用它們的析構(gòu)函數(shù)。但是假設(shè)在這個(gè)調(diào)用期間,第二個(gè) Widgets 的析構(gòu)函數(shù)又拋出一個(gè)異?!,F(xiàn)在有兩個(gè)異常同時(shí)在活動(dòng)中,對(duì)于 C++ 來說這太多了。在非常巧合的條件下發(fā)生這樣兩個(gè)同時(shí)活動(dòng)的異常,程序的執(zhí)行會(huì)終止或者引發(fā)未定義行為。在本例中,將引發(fā)未定義行為。與此相同,使用任何標(biāo)準(zhǔn)庫(kù)容器(比如,list,set),任何 TR1中的容器,甚至是一個(gè)數(shù)組,都可能會(huì)引發(fā)未定義問題。并非必須是容器或數(shù)組才會(huì)陷入麻煩。程序夭折或未定義行為是析構(gòu)函數(shù)引發(fā)異常的結(jié)果,即使沒有使用容器或數(shù)組也會(huì)如此。C++ 不喜歡引發(fā)異常的析構(gòu)函數(shù)。 這比較容易理解,但是如果你的析構(gòu)函數(shù)需要執(zhí)行一個(gè)可能失敗而拋出異常的操作,該怎么辦呢?例如,假設(shè)你與一個(gè)數(shù)據(jù)庫(kù)連接類一起工作:
    class DBConnection {
    public:
     ...
     static DBConnection create(); // function to return
     // DBConnection objects; params
     // omitted for simplicity
    void close(); // close connection; throw an
    }; // exception if closing fails