【问题标题】:Looking at std::unique_ptr and its nullptr_t constructor查看 std::unique_ptr 及其 nullptr_t 构造函数
【发布时间】:2015-01-27 01:28:08
【问题描述】:

我试图理解为什么unique_ptr 有一个 nullptr_t 构造函数

constexpr unique_ptr::unique_ptr( nullptr_t );

我以为这是因为普通的单参数构造函数是显式的,因此会拒绝 nullptr 值:

explicit unique_ptr::unique_ptr( pointer p );

但是当我构建一个示例时,它编译得很好:

namespace ThorsAnvil
{
    template<typename T>
    class SmartPointer
    {
        public:
            SmartPointer()      {}
            explicit SmartPointer(T*){}
    };
}


template<typename T>
using SP    = ThorsAnvil::SmartPointer<T>;
int main()
{

    SP<int>     data1;
    SP<int>     data2(new int);  // fine
    SP<int>     data3(nullptr);  // fine
}

这是输出:

> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix
> g++ -Wall -Wextra -std=c++11 SP1.cpp

为什么 std::unique_ptr 需要带有 nullptr_t 参数的额外构造函数?

【问题讨论】:

  • 我凭空猜测是为了优化,因为它被声明为constexpr
  • nullptr_t 构造函数也是explicit吗?
  • @templatetypedef:不。只是 contexpr。
  • 这将失败:SP&lt;int&gt; data; data = nullptr;
  • @CrappyExperienceBye 这可能就是你的答案——它允许直接分配nullptr。这是一个充分的理由吗?

标签: c++ c++11 unique-ptr nullptr


【解决方案1】:
SP<int>     data3(nullptr);  // fine

您正在使用直接初始化,这会导致考虑 explicit 构造函数。尝试以下操作,您的代码将无法编译

SP<int>     data4 = nullptr;

现在添加以下构造函数,上面的行将编译

SmartPointer(std::nullptr_t){}

所以nullptr_t 构造函数使unique_ptr 在您想要将其初始化为nullptr 的情况下表现得像一个原始指针,但在您可能实际分配它的其他情况下避免任何令人惊讶的所有权转移一个原始指针。

【讨论】:

  • SP&lt;int&gt; data5 = new int; 也失败了。
  • @CrappyExperienceBye 那应该会失败,请参阅我刚刚添加的关于“令人惊讶的”所有权转让的最后一段。
  • 所以基本上这是允许SP&lt;int&gt; newData = nullptr;,并且有一个等效的分配版本允许newData = nullptr;。所以我们可以很容易地重置 unqiue_ptr 但不会意外分配它。
  • @CrappyExperienceBye 是的,不仅仅是初始化/分配。想想一个函数void foo(unique_ptr&lt;Type&gt;) {...} 显然该函数拥有参数的所有权。假设有人将其称为 Type *t = new Type; foo(t); 进行编译并且函数默默地假设所有权是不可取的行为。
  • 是的,我理解关于T* 的明确表达。我只是想看看为什么对nullptr 的特殊情况有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-20
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
相关资源
最近更新 更多