大多数人说 永远不要 从析构函数中抛出异常——这样做会导致未定义的行为。 Stroustrup 指出 “向量析构函数为每个元素显式调用析构函数。这意味着如果元素析构函数抛出,向量销毁失败……确实没有很好的方法来防止析构函数引发的异常,所以库不保证元素析构函数是否抛出”(来自附录 E3.2) 。
这篇文章 似乎另有说法 - 抛出析构函数或多或少是可以的。
所以我的问题是——如果从析构函数中抛出导致未定义的行为,你如何处理析构函数期间发生的错误?
如果在清理操作过程中发生错误,您是否忽略它?如果它是一个可以在堆栈中处理但不能在析构函数中正确处理的错误,那么从析构函数中抛出异常是否有意义?
显然,这类错误很少见,但也有可能。
原文由 Greg Rogers 发布,翻译遵循 CC BY-SA 4.0 许可协议
从析构函数中抛出异常是危险的。
如果另一个异常已经在传播,则应用程序将终止。
这基本上归结为:
任何危险的事情(即可能引发异常)都应该通过公共方法(不一定直接)来完成。然后,您的类的用户可以通过使用公共方法并捕获任何潜在的异常来潜在地处理这些情况。
然后,析构函数将通过调用这些方法(如果用户没有明确地这样做)来完成对象,但是任何抛出的异常都会被捕获并丢弃(在尝试修复问题之后)。
因此,实际上您将责任转嫁给了用户。如果用户能够纠正异常,他们将手动调用适当的函数并处理任何错误。如果对象的用户不担心(因为对象将被销毁),那么析构函数将负责处理业务。
一个例子:
标准::fstream
close() 方法可能会引发异常。如果文件已打开,则析构函数调用 close(),但要确保任何异常都不会传播到析构函数之外。
因此,如果文件对象的用户想要对与关闭文件相关的问题进行特殊处理,他们将手动调用 close() 并处理任何异常。另一方面,如果他们不关心,那么析构函数将被留下来处理这种情况。
Scott Myers 在他的“Effective C++”一书中有一篇关于这个主题的优秀文章
编辑:
显然也在“更有效的 C++”中
第 11 条:防止异常离开析构函数