c++:从析构函数抛出异常

c++: Throwing exception from a destructor

本文关键字:抛出异常 析构函数 c++      更新时间:2023-10-16

这是面试问题。我告诉他,如果堆栈展开已经在进行,程序可能会终止。除此之外,如果异常得到了正确处理,您还会看到任何问题吗?我告诉他,只要事情处理得当就行。但是他看起来对我的回答不太满意。

那么,您无法知道是否已经存在活动异常。如果有,如果让另一个异常从析构函数中逃脱,程序将终止。

所以我不太明白你的论点:

我告诉他只要处理得当就可以。

除了一开始就不让它从析构函数中逃脱之外,你如何"适当地处理"它呢?如果我是面试官,我下一个问题就是这个。

如果从析构函数抛出,这意味着异常实际上离开了析构函数。所以正确处理部分是不可能的:您无法知道它将如何处理。

还有一个微妙的问题:在许多重要的情况下,除非假定析构函数不会抛出异常,否则编写异常安全的代码是不可能的(或者至少是非常昂贵的)。如果析构函数抛出,类的用户将无法用它编写好的代码。例如:除非保证容器所包含对象的析构函数不抛出,否则不可能为容器编写异常安全的析构函数。这里不会调用terminate(),但是容器析构函数会泄漏资源。

从析构函数抛出没有意义

析构函数中唯一可恢复的错误是关闭/刷新文件时的I/O错误(或与网络有关的类似错误,等等)。但从这些状况中恢复是微不足道的。只需报告错误并继续。不管怎样,你不需要那个文件,你刚刚试图关闭它!因为一个你根本不需要的文件中的错误而放弃你正在做的事情是一种浪费。

析构函数中可能发生的所有其他类型的故障,例如无法解锁互斥锁或释放内存块,可能是不可恢复的,因此需要调用terminate()

另一方面,如果分配资源时出现错误,或者在计算过程中执行I/O失败,则会抛出保证,因为计算无法继续。但这不应该发生在析构函数中,或者如果发生了,应该在析构函数中处理(为什么?同样,让它传播出去是没有意义的,这不会停止错误并且会放弃可以愉快地继续进行的计算)。

因此,即使从析构函数中抛出是完全安全且定义良好的,它也不会给我们带来太多好处。