在派生类的析构函数中抛出异常
Throwing exception in destructor of derived class
我正在编译一个c++库,我有一个析构函数和noexcept
的问题。
我的理解是,从c++ 11开始,析构函数内部的noexcept(...)
的默认值发生了变化。特别是,现在析构函数默认为noexcept
(即noexcept(true)
)。
现在,我有一个库,由于某些类的析构函数可能抛出的事实,我得到许多编译器警告,但它没有标记为noexcept(false)
。所以我决定改变这一点,并添加规范。然而,这些类继承自一些共同的父类Base
,所以这迫使我将它也添加到父类析构函数中,否则我得到编译器错误overriding ‘virtual Base::~Base() noexcept
。
当然,我也可以将 我有两个问题: 1)有什么办法解决这个问题吗?我不能删除抛出的几个派生类中的抛出,因为它们很重要。 2)我不确定由于将 编辑:在一个侧面说明,有没有办法改变 编辑:因为有很多反馈,我应该编辑一下,加上一些注释: 1)库不是我写的,我当然也不打算重写许多类的析构函数。不得不将 2)当我说"我不能删除抛出的几个派生类中的抛出,因为它们很重要"时,我的意思是我相信代码应该在这种情况下终止,因为发生了一些非常糟糕的事情,并且无论如何都可能发生未定义的行为。这次投掷至少对发生的事情有一点解释。 3)我明白,抛出派生类的析构函数是不好的,因为它可能会泄漏,因为父类的析构函数没有被调用(这是正确的吗?)如果应该终止程序(以避免以后出现难以理解的bug),并且仍然让用户知道发生了什么,那么什么是一种干净的方法呢?noexcept(false)
添加到基类中(实际上,据我所知,在那里添加它就足够了),但是有很多类继承自Base
,并且它们都继承noexcept(false)
属性(据我所知)。然而,基类析构函数本身永远不会抛出,而且只有少数派生类可以抛出。因此,仅为少数类标记基类析构函数noexcept(false)
似乎是一种浪费。noexcept(false)
添加到库中(实际上)所有类的基类中,编译器优化可能会降低多少。什么时候(如果有的话)我应该关心这件事?noexcept
的默认值在一个项目?也许是一个编译器选项?noexcept(false)
添加到一些基类中已经足够痛苦了。而使用其他库也不是一种选择(出于编程之外的不同原因)。
如果析构函数为虚函数,则派生析构函数不能为noexcept(false)
,除非基类析构函数也是noexcept(false)
。
想想看:虚函数的意义在于,即使调用者只知道基类,也可以调用派生类。如果在Base*
上调用delete
,如果Base
承诺其析构函数不会抛出异常,则可以在没有任何异常处理代码的情况下编译该调用。如果指针指向一个Derived
实例,而该实例的析构函数却抛出异常,那就不好了。
尝试修改派生的析构函数,使其不会抛出异常。如果不可能,请将noexcept(false)
添加到基类析构函数中。
我不确定将
noexcept(false)
添加到库中(实际上)所有类的基类中会降低多少编译器优化。什么时候(如果有的话)我应该关心这件事?
你不应该关心基于noexcept
对析构函数声明的编译器优化。围绕noexcept
声明的大多数优化来自于检测操作是noexcept
并基于此执行更有效的操作的代码。即显式元编程。
为什么这对析构函数不重要?好吧,考虑c++标准库。如果给vector
一个类型,而包含对象的析构函数之一抛出,则会得到未定义的行为。对于标准库中的所有都是如此(除非显式地标记)。
这意味着标准库不会费心检查你的析构函数是否为noexcept
。它可以,而且几乎肯定会,假定没有析构函数发出异常。如果有的话……那是你的错。
因此,您的代码可能不会因为在析构函数上使用noexcept(false)
而运行变慢。是否在基类的析构函数上使用noexcept(false)
的决定不应该受到性能问题的影响。
- 如何检测构造函数是否与抛出的析构函数无关
- 在析构函数内部处理异常(但不抛出)
- new[] / delete[] 并在C++中抛出构造函数/析构函数
- 抛出可由C++98和C++1x编译的析构函数.有更好的方法吗
- C++使用RAII和抛出的析构函数
- 可能std::向量中的元素具有抛出的析构函数
- 为什么在数组创建期间抛出未捕获的异常时不调用析构函数C++?
- 抛出异常并返回函数的结果
- 清理C++异常析构函数中的代码
- 正在从vtable的析构函数安全抛出异常
- 抛出异常时未调用析构函数
- C++11 异常的析构函数允许现在抛出?
- 调用从对象中移出的析构函数的原因
- 为什么不能从析构函数抛出异常,但可以从复制构造函数抛出异常
- c++:从析构函数抛出异常
- 构造函数中抛出的异常:被调用析构函数
- 空std::list在调用析构函数时抛出异常
- 在派生类的析构函数中抛出异常
- 为什么在抛出异常时析构函数调用两次
- c++从析构函数抛出异常