我有一个类的析构函数是noexcept(false)
。我知道它只在特定情况下抛出,并且我想将它用作具有noexcept
析构函数的类的成员变量。从…起https://en.cppreference.com/w/cpp/language/function-try-block我读了";从函数体中的任何语句、(对于构造函数(从任何成员或基构造函数、(对于析构函数(从任意成员或基析构函数抛出的每个异常,都会像在常规try块中抛出异常一样,将控制权转移到处理程序序列"这让我认为这应该是正确的:
#include <exception>
class ConditionallyThrowingDtor {
public:
bool willThrow = true;
ConditionallyThrowingDtor() = default;
~ConditionallyThrowingDtor() noexcept(false) {
if (willThrow) {
throw std::exception();
}
}
};
class NonThrowingDtor {
public:
ConditionallyThrowingDtor x;
~NonThrowingDtor() noexcept try {
x.willThrow = false;
} catch (...) {
// Ignore because we know it will never happen.
}
};
int main() {
// ConditionallyThrowingDtor y; // Throws on destruction as expected.
NonThrowingDtor x;
}
https://godbolt.org/z/ez17fx(MSVC(
我对noexcept
和~NonThrowingDtor()
上的函数try块的理解是,noexcept
保证它不会抛出(并且它本质上是通过执行try { ... } catch (...) { std::terminate(); }
来实现的https://en.cppreference.com/w/cpp/language/noexcept_spec.但是带有catch (...)
并且没有额外抛出的函数try块应该保证它永远不会抛出。Clang对此表示同意,但正如godbolt链接所示,MSVC表示
<source>(23): warning C4297: 'NonThrowingDtor::~NonThrowingDtor': function assumed not to throw an exception but does
<source>(23): note: destructor or deallocator has a (possibly implicit) non-throwing exception specification
~NonThrowingDtor() noexcept try {
x.willThrow = false;
} catch (...) {
// Ignore because we know it will never happen.
}
是";错误的";相当于
~NonThrowingDtor() noexcept try {
x.willThrow = false;
} catch (...) {
throw;
}
所以简单的
~NonThrowingDtor() noexcept
{
x.willThrow = false;
}
为了不传播异常,您必须显式使用return
:
~NonThrowingDtor() noexcept try {
x.willThrow = false;
} catch (...) {
return; // Required to not propagate exception.
}
不幸的是,msvc仍然用这个不抛出的表单进行警告
(另一方面,clang/gcc在这种情况下不会对隐式发出警告(但对显式(throw
发出警告(。