2012-01-28 166 views
6

考慮下面的代碼析構函數不叫:當異常被拋出

#include <iostream> 
using namespace std; 

class Test { 
    static int count; 
    int id; 
public: 
    Test() { 
    count++; 
    id = count; 
    cout << "Constructing object number " << id << endl; 
    if(id == 4) 
     throw 4; 
    } 
    ~Test() { cout << "Destructing object number " << id << endl; } 
}; 

int Test::count = 0; 

int main() { 
    try { 
    Test array[5]; 
    } catch(int i) { 
    cout << "Caught " << i << endl; 
    } 
} 

上面的代碼產生以下輸出:

Constructing object number 1 
Constructing object number 2 
Constructing object number 3 
Constructing object number 4 
Destructing object number 3 
Destructing object number 2 
Destructing object number 1 
Caught 4 

我想析構函數總是被調用時,對象變得超出範圍即使發生異常時也是如此。爲什麼在這種情況下不調用其中的Test實例的析構函數?

+0

我已經編輯你的問題到更適合堆棧溢出的東西。請按照[問題指南](http://stackoverflow.com/questions/how-to-ask)以備將來參考,否則您的問題可能會被降低/關閉。 – 2012-01-28 06:19:15

回答

8

你正在創建5Test對象的數組,但你創建3完整對象後,你拋出一個異常,該異常而在第4對象的構造函數拋出。 4 th對象的構造直到達到構造函數的大括號才完成。

堆棧解開呼籲在創建它們以相反的順序那些3完全構造的對象的析構函數,由於第45個對象從未構造的析構函數爲它們不會被調用。

異常規則是:
一旦拋出異常,將調用該範圍內所有完全創建的對象的析構函數。
一個完全創建的對象是其構造函數被幹淨地調用而沒有任何異常的對象。

+0

這[本週導師文章(#66)](http://www.gotw.ca/gotw/066.htm)與這種情況尤其相關。 – 2012-01-28 06:20:32

+0

關閉 - 只有3個完全構建的對象,所以只有3個析構函數被調用。 – 2012-01-28 07:09:01

+0

@ChrisDodd:哦,很好看。我搞砸了讀取痕跡。 – 2012-01-28 07:10:47

3

相反ID後書面方式將COUT語句=計數如下所述: -

id = count; 
    cout << "Constructing object number " << id << endl; 
    if(id == 4) 
    throw 4; 

你應該throw語句後寫的。那會給你一個更好的 圖片發生了什麼事。是這樣的: -

Test() { 
count++; 
id = count; 
if(id == 4) 
    throw 4; 
cout << "Constructing object number " << id << endl; 
    } 

的O/P本來: - 構建對象號1 構建對象號2 構建對象號3 超聲破壞對象號3 超聲破壞對象號2 超聲破壞對象號1 Caught 4