抛出C ++后调用析构函数吗?

我运行了一个示例程序,确实调用了堆栈分配对象的析构函数,但这是由标准保证的吗?

是的,它被保证(提供exception被捕获),直到调用析构函数的顺序

C ++ 11 15.2构造函数和析构函数[except.ctor]

1当控件从throwexpression式传递给处理函数时,对于自try块input后构造的所有自动对象调用析构函数。 自动对象以与其构造完成相反的顺序被销毁。

而且,如果在构造对象时引发exception,则部分构造对象的子对象将被保证正确销毁:

2任何存储持续时间的对象,其初始化或销毁都由exception终止,将为所有完全构造的子对象(不包括类联合类的变体成员)执行析构函数,也就是说,对于主构造函数(12.6.2)已经完成执行,析构函数尚未开始执行。 同样,如果对象的非委托构造函数已经完成执行,并且该对象的委托构造函数以exception退出,则会调用该对象的析构函数。 如果对象是以新expression式分配的,则会调用匹配的释放函数(3.7.4.2,5.3.4,12.5)(如果有),以释放对象占用的存储空间。

整个过程被称为“堆栈展开”:

3为从try块到throw-expression的path上构造的自动对象调用析构函数的过程称为“堆栈展开”。如果在堆栈展开过程中调用的析构函数退出时出现exception,则调用std :: terminate(15.5。 1)。

堆栈展开是广泛使用的称为资源获取初始化(RAII)的技术的基础。

请注意,如果未捕获到exception,堆栈展开不一定会完成。 在这种情况下,堆栈展开是否完成取决于实现。 但是,无论堆栈展开是否完成,在这种情况下,您都可以保证最终调用std::terminate

C ++ 11 15.5.1 std :: terminate()函数[except.terminate]

2 …在没有find匹配的处理程序的情况下,在std::terminate()被调用之前,是否实现定义堆栈是否被解开。

是的,析构函数保证在堆栈展开时调用,包括由于抛出exception而展开。 只有很less的例外,你必须记住:

  • 如果在其构造函数中引发exception,则不调用该类的析构函数。
  • 如果在构build初始化列表捕获块中被捕获,exception会自动重新抛出。