按值捕获异常的参数时,调用析构函数的顺序是什么?

时间:2010-07-22 20:59:51

标签: c++ exception-handling

在以下代码中,调用bqe的析构函数的顺序是什么,以及在处理异常之前调用的顺序。 (“cout ......”部分是原始问题的剩余部分)

#include <iostream> 
using namespace std; 

class A { 
public: 
  A(int arg) : m(arg) { 
    cout << "A::A(int) " << m << endl; 
    m = 2*arg; 
  } 
  virtual void f() { 
    cout << "A::f() " << m << endl; 
  } 
  void g() { 
    cout << "A::g(A) " << m << endl; 
  } 

  int m; 
}; 

class B : public A { 
public: 
  B(int arg) : A(arg) { 
    cout << "B::B(int) " << m << endl; 
    m = 3*arg; 
  } 
  ~B() {
    cout << "B::~B()" << endl;
  } 
  void f() {
    cout << "B::f(A&) " << m << endl; 
  } 
  virtual void g() { 
    B q(*this);
    throw q; 
    cout << "B::g(A) " << m << endl; 
  } 
}; 

int main() { 
  try { 
    B b(1);
    b.g(); 
  } catch (A e) { 
    cout << "Error: "; 
    e.f(); 
  } 
  return 0; 
} 

如果有可能,你能解释一下原因吗? 谢谢。

1 个答案:

答案 0 :(得分:1)

首先调用

q的析构函数,因为它是作为堆栈展开的第一部分而被销毁的(最内部作用域中的局部对象首先被销毁),然后调用b的析构函数,也作为堆栈展开的一部分。在进入catch块之前,两者都被销毁。堆栈展开在异常处理程序执行之前发生。

请记住,异常对象被复制,因此B::g() q创建b的副本e的副本(异常对象),其生命周期延长到了catch块的末尾。它用于初始化(切片!)q

异常对象本身的析构函数(e的副本)在throw;被销毁后立即执行(因为处理程序不通过{{1}}退出)。此排序在标准中指定。