std::unique_ptr的constexpr构造函数

16

此处所示std::unique_ptr有两个针对空指针的constexpr构造函数:

constexpr unique_ptr();
constexpr unique_ptr( nullptr_t );

我对这两个构造函数有两个问题:

  1. 为什么我们需要两个构造函数?我们不能只声明一个,如下:

    constexpr unique_ptr( nullptr_t = nullptr );
    
  2. constexpr真的有用吗?我在我的代码中尝试使用它,但它无法编译(g++ 6.1.0,-std=c++14):

    constexpr std::unique_ptr<int> p;
    // error: the type 'const std::unique_ptr<int>' of constexpr variable 'p'
    // is not literal because 'std::unique_ptr<int>' has a non-trivial destructor
    

3
那与这个同样的问题相关联。 - Dutow
LOL,复制/粘贴失败。但是oldrinb的答案链接到了我本来想链接的那个。 - T.C.
2个回答

13

对于(1),需要考虑它确保无参构造函数 unique_ptr() 和空指针构造函数 unique_ptr(nullptr_t) 具有相同的编译时保证,即两者都是 constexpr。我们可以在 §20.8.1.2 中看到它们之间的区别:

constexpr unique_ptr() noexcept;
explicit unique_ptr(pointer p) noexcept;
...
constexpr unique_ptr(nullptr_t) noexcept
: unique_ptr() { }

为什么这两个构造函数没有被合并成一个带有默认值的构造函数,可能是历史原因。

关于(2),为什么我们应该在有非平凡析构函数时关注constexpr,可以考虑此处给出的答案:

constexpr 构造函数可用于常量初始化,作为静态初始化的一种形式,在任何动态初始化之前都保证已发生。

例如,给定全局std::mutex

std::mutex mutex;

在符合标准的实现中(即非MSVC),其他对象的构造函数可以安全地锁定和解锁mutex,因为std::mutex的构造函数是constexpr


9
关于Q1,nullptr_t构造函数是在原始提案(N1586)之后的N2435中添加的。

添加一个简单的重载,可以在一行内指定,这比尝试聪明地写代码干净得多,特别是因为[member.functions]已经允许实现者使用“聪明”的版本如果他们想要的话。

1
那么标准中指定的当前两个构造函数功能上应该等效于我问题中的那一个,是吗? - Zizheng Tai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接