抛出异常时不调用析构函数

时间:2012-01-28 06:09:41

标签: c++ algorithm

请考虑以下代码:

#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实例'析构函数之一?

2 个答案:

答案 0 :(得分:8)

您正在创建一个5 Test个对象的数组,但在创建3 完整对象后抛出异常,异常会在4对象的构造函数。在到达构造函数的右括号之前,4对象的构造尚未完成。

堆栈以与创建它们相反的顺序解析那些3完全构造的对象的析构函数,因为45对象从未构造为析构函数它们从未被称为。

例外规则是:
抛出异常后,将调用该范围内所有完全创建的对象的析构函数 完全创建的对象是其构造函数被干净地调用而没有任何异常的对象。

答案 1 :(得分:3)

而不是在id = count之后写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           抓到4