d'tor 的函数尝试块是否应该允许处理抛出成员变量 d'tor?
Should function-try-block of d'tor allow handling of throwing member-variable d'tor?
我有一个class,它的析构函数是noexcept(false)
。我知道它只在某些情况下抛出,我想将它用作 class 和 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()
上的函数尝试块的理解是 noexcept
保证它不会抛出(并且它通过本质上做 try { ... } catch (...) { std::terminate(); }
https://en.cppreference.com/w/cpp/language/noexcept_spec。但是带有 catch (...)
且没有额外抛出的函数尝试块应该保证它永远不会抛出。Clang 对此没有问题,但正如神栓 link 所示,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
在这种情况下)。
我有一个class,它的析构函数是noexcept(false)
。我知道它只在某些情况下抛出,我想将它用作 class 和 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()
上的函数尝试块的理解是 noexcept
保证它不会抛出(并且它通过本质上做 try { ... } catch (...) { std::terminate(); }
https://en.cppreference.com/w/cpp/language/noexcept_spec。但是带有 catch (...)
且没有额外抛出的函数尝试块应该保证它永远不会抛出。Clang 对此没有问题,但正如神栓 link 所示,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
在这种情况下)。