先上代码 实例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <iostream> using namespace std ;class B {public : ~B(){ cout <<"B" <<endl ; }; }; int main () { try { B b; throw B(); } catch (const B &b){ cout <<"end" <<endl ; } }
结论:抛出异常后,首先析构从try语句内的局部变量,然后再执行catch语句,执行完后,再执行对throw后面对象的析构
实例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <iostream> using namespace std ;class B {public : ~B(){ cout <<"B" <<endl ; }; }; int main () { try { B b; throw b; } catch (const B &b){ cout <<"end" <<endl ; } }
结论:throw后使用了b对象,实际上是对b对象的一次拷贝,所以析构的先析构b对象,再析构b对象的副本,析构了两次
实例3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <iostream> using namespace std ;class B {public : ~B(){ cout <<"B" <<endl ; }; }; class A {public : ~A(){ cout <<"A" <<endl ; }; }; class C {public : ~C(){ cout <<"C" <<endl ; }; }; int main () { try { C c; { B b; A a; throw b; } } catch (const B &b){ cout <<"end" <<endl ; } }
结论:按声明时相反的顺序先析构掉本层作用域内的对象,再往上析构掉高层作用域中的对象,依次上推直到将throw之前的在本try语句块中声明的所有对象都析构掉为止
总结 throw的时候将被抛出的对象拷贝一份到专用的异常栈上,接着按声明时相反的顺序先析构掉本层作用域内的对象,再往上析构掉高层作用域中的对象,依次上推直到将throw之前的,在本函数中声明的所有对象都析构掉为止。然后再执行catch中的相关语句,最后才析构掉拷贝对象。