在 C++11 中,我的理解是默认析构函数是隐式的noexcept(true)
,除了:
如果我有一个C
具有显式标记的析构函数的类noexcept(false)
(可能是因为它出于某种奇怪的原因而抛出,并且我知道您不应该这样做,以及为什么),那么任何派生自C
或包含类型成员的类的析构函数C
也变成了noexcept(false)
。
但是,包含 a 的类std::shared_ptr<C>
显然不会自动将其析构函数切换为,包含 a ,等noexcept(false)
也是如此。std::weak_ptr<C>
std::unique_ptr<C>
这是一个完整的例子:
#include <type_traits>
#include <memory>
struct Normal {
~Normal() {
}
};
struct ThrowsInDtor {
~ThrowsInDtor() noexcept(false) {
throw 42;
}
};
template<typename T>
struct Wrapper {
T t;
};
template<typename T>
struct UniquePtrWrapper {
std::unique_ptr<T> t;
};
template<typename T>
struct SharedPtrWrapper {
std::shared_ptr<T> t;
};
static_assert(std::is_nothrow_destructible<Normal>::value, "A"); // OK
static_assert(!std::is_nothrow_destructible<ThrowsInDtor>::value, "B"); // OK
static_assert(std::is_nothrow_destructible<Wrapper<Normal>>::value, "C"); // OK
static_assert(!std::is_nothrow_destructible<Wrapper<ThrowsInDtor>>::value, "D"); // OK
static_assert(std::is_nothrow_destructible<UniquePtrWrapper<Normal>>::value, "E"); // OK
static_assert(!std::is_nothrow_destructible<UniquePtrWrapper<ThrowsInDtor>>::value, "F"); // FAILS
static_assert(std::is_nothrow_destructible<SharedPtrWrapper<Normal>>::value, "G"); // OK
static_assert(!std::is_nothrow_destructible<SharedPtrWrapper<ThrowsInDtor>>::value, "H"); // FAILS
F 和 H 失败对我来说似乎很奇怪。我曾期望拥有/引用类型的析构函数的 noexcept 状态会传播到智能指针析构函数,大概是通过noexcept(std::is_nothrow_destructible<T>::value)
智能指针析构函数声明中的 noexcept 表达式。
但是标准没有提到这一点,我看过的标准库代码也没有这样做。
有谁知道为什么标准智能指针不将实例化类型的 noexcept 析构函数状态传播到智能指针析构函数?