unique_ptr<T,Deleter> 构造函数要求 Deleter 不被抛出

unique_ptr<T,Deleter> constructor requires that Deleter is nothrow

unique_ptr (constructor) @ cppreference

unique_ptr( pointer p, /* see below */ d1 ) noexcept;
(3) 
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
(4)

这里有2个构造器,对case Deleter的描述是非引用

a) If D is non-reference type A, then the signatures are:
unique_ptr(pointer p, const A& d) noexcept;
(1) (requires that Deleter is nothrow-CopyConstructible)
unique_ptr(pointer p, A&& d) noexcept;
(2) (requires that Deleter is nothrow-MoveConstructible)

我检查了 gcc 和 llvm 代码,但我没有看到 nothrow 要求得到执行。构造函数 3-4 被标记为 noexcept,因此在调用其构造函数时 Deleter 不应抛出是有道理的。但我不确定为什么在他们提供的示例中,构造函数未标记为 noexcept.

struct D { // deleter
    D() {};
    D(const D&) { std::cout << "D copy ctor\n"; }
    D(D&) { std::cout << "D non-const copy ctor\n";}
    D(D&&) { std::cout << "D move ctor \n"; }
    void operator()(Foo* p) const {
        std::cout << "D is deleting a Foo\n";
        delete p;
    };
};

I checked both gcc and llvm code but I don't see nothrow requirement is enforced.

它不是直接强制执行的。
这是 actual words from the standard:

For the first constructor, if D is not a reference type, D shall meet the Cpp17CopyConstructible requirements and such construction shall not exit via an exception. For the second constructor, if D is not a reference type, D shall meet the Cpp17MoveConstructible requirements and such construction shall not exit via an exception.

也就是说,如果您的 copy/move 构造函数通过异常退出,则您有未定义的行为。 [ 'shall' 在这种情况下是对用户的要求。 ]

如果幸运的话,程序会调用 terminate 并显示一条好消息。但是,您无法保证。

(稍后)注意:要求不是它们是 noexcept,而是它们不会通过异常退出。这就是为什么 cppreference 上的示例很好。