2012-01-28 157 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