Luc*_*ore 43 c++ exception-handling raii try-catch
我运行了一个示例程序,确实调用了堆栈分配对象的析构函数,但这是否由标准保证?
NPE*_*NPE 59
是的,它是有保证的(如果捕获了异常),直到调用析构函数的顺序:
C++ 11 15.2构造函数和析构函数[except.ctor]
1当控件从throw-expression传递到处理程序时,将为输入try块后构造的所有自动对象调用析构函数.自动对象按照完成构造的相反顺序销毁.
此外,如果在对象构造期间抛出异常,则保证部分构造的对象的子对象被正确销毁:
2由异常终止其初始化或销毁的任何存储持续时间的对象将为其所有完全构造的子对象(不包括类似联合类的变体成员)执行析构函数,即对于主要构造函数的子对象执行(12.6.2)已完成执行,析构函数尚未开始执行.类似地,如果对象的非委托构造函数已完成执行并且该对象的委托构造函数以异常退出,则将调用该对象的析构函数.如果对象是在new-expression中分配的,则调用匹配的释放函数(3.7.4.2,5.3.4,12.5)(如果有)以释放对象占用的存储空间.
整个过程称为"堆栈展开":
3为从try块到throw-expression的路径构造的自动对象调用析构函数的过程称为"堆栈展开".如果在堆栈展开期间调用的析构函数以异常退出,则调用std :: terminate(15.5. 1).
堆栈展开形成了被称为资源获取初始化(RAII)的广泛使用的技术的基础.
请注意,如果未捕获异常,则不必执行堆栈展开.在这种情况下,是否完成堆栈展开的实现.但是,无论是否完成堆栈展开,在这种情况下,您都可以保证最终调用std::terminate.
C++ 11 15.5.1 std :: terminate()函数[except.terminate]
2 ...在没有找到匹配处理程序的情况下,无论堆栈是否在
std::terminate()被调用之前被展开,它都是实现定义的.
小智 7
是的,保证在堆栈展开时调用析构函数,包括因抛出异常而展开.您必须记住的例外情况很少: