为什么std :: unique_ptr重置与赋值不一样?

时间:2018-05-03 03:11:54

标签: c++ c++11 initialization variable-assignment unique-ptr

我想了解原因

std::unique_ptr<MyClass> p = new MyClass; 

不起作用,但是

std::unique_ptr<MyClass> p;
p.reset(new MyClass);

很好。我有点理解他们是如何不同的,但我想知道为什么做出选择使他们与众不同。分配与重置不一样的危险是什么?

2 个答案:

答案 0 :(得分:19)

首先,std::unique_ptr<MyClass> p = new MyClass;不是作业,而是copy initialization。并且它不起作用,因为带有原始指针的constructor of std::unique被标记为explicit

explicit unique_ptr( pointer p ) noexcept;

它被声明为explicit以避免意外(可能是危险的)隐式转化,例如:

void foo(std::unique_ptr<int> uptr);

int *rptr = new int;
foo(rptr); // suppose rptr is implicitly converted to std::unique_ptr<int>
           // then the ownership is passed to the parameter uptr

// when foo() returns uptr is destroyed; the pointer managed by it is deleted too
// since rptr has been deleted continue to deference on it leads to UB
*rptr = 42; // UB

请注意,copy initialization中不考虑explicit构造函数(例如std::unique_ptr<MyClass> p = new MyClass;)。您可以在direct initialization中使用它们(例如std::unique_ptr<MyClass> p (new MyClass);)。它们用于禁止隐式转换,但您可以执行显式转换。与reset的使用一样,您必须明确明确这些事情,以显示(并使自己)您对自己所做的事情非常肯定。< / p>

BTW:来自原始指针的分配也不起作用,因为std::unique_ptr没有重载的赋值运算符将原始指针作为参数。由于上述原因,原始指针不能隐式转换为std::unique_ptr,因此移动赋值运算符(以std::unique_ptr为参数)赢得了“t”被认为是。

答案 1 :(得分:6)

  

我想了解原因   std::unique_ptr<MyClass> p = new MyClass;   不起作用

与@songyuanyao提到的相同的原因,即它声明为explicit的地方,告诉您仍然可以在超出explicit的{​​{3}}中对其进行初始化:

// Valid, since now it's 'explicit'
std::unique_ptr<MyClass> p { new MyClass{} };