6

在 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 析构函数状态传播到智能指针析构函数?

4

1 回答 1

6

std::shared_ptr<T>被设计为可与不完整的 一起使用T,因此在声明其析构函数时无法获取您要求的信息。此外,您可以这样做:

std::shared_ptr<void> dummy = std::make_shared<T>(); // for some complete T

现在应该noexceptstd::shared_ptr<void>什么?std::shared_ptr这是来自的 POV的运行时信息。

对于std::unique_ptr,有

20.7.1.2.2 unique_ptr 析构函数 [unique.ptr.single.dtor]

1 ~unique_ptr();

要求:表达式get_deleter()(get())格式正确,行为明确,不抛出异常。[注:使用default_delete要求T是一个完整的类型。——尾注]

这意味着删除器需要确保它不会抛出 - 这不一定取决于 的析构函数T,即,当您使用空删除器时。

于 2013-10-22T21:41:52.893 回答