C++ 为什么std::unique_ptr reset与赋值不同?

C++ 为什么std::unique_ptr reset与赋值不同?,c++,c++11,initialization,variable-assignment,unique-ptr,C++,C++11,Initialization,Variable Assignment,Unique Ptr,我正在努力理解为什么 std::unique_ptr<MyClass> p = new MyClass; std::unique_ptr p=新MyClass; 不起作用,但是 std::unique_ptr<MyClass> p; p.reset(new MyClass); std::unique\u ptr p; p、 重置(新MyClass); 很好。我多少能理解它们的不同之处,但我想知道为什么要选择使它们不同。赋值与重置不同的危险是什么?首先,std::

我正在努力理解为什么

std::unique_ptr<MyClass> p = new MyClass; 
std::unique_ptr p=新MyClass;
不起作用,但是

std::unique_ptr<MyClass> p;
p.reset(new MyClass);
std::unique\u ptr p;
p、 重置(新MyClass);

很好。我多少能理解它们的不同之处,但我想知道为什么要选择使它们不同。赋值与重置不同的危险是什么?

首先,
std::unique\u ptr p=new MyClass不是作业,而是作业。它不起作用,因为获取原始指针被标记为
explicit

// Valid, since now it's 'explicit'
std::unique_ptr<MyClass> p { new MyClass{} };
它被声明为
显式
,以避免意外的(可能是危险的)隐式转换,例如:

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
void foo(std::unique\u ptr uptr);
int*rptr=新的int;
foo(rptr);//假设rptr隐式转换为std::unique\u ptr
//然后所有权被传递给参数uptr
//当foo()返回时,uptr被销毁;由它管理的指针也被删除
//由于rptr已被删除,因此继续尊重它会导致UB
*rptr=42;//乌兰巴托
请注意,
explicit
构造函数在中不被考虑(例如
std::unique\u ptr p=new MyClass;
)。您可以在中使用它们(例如
std::unique_ptr p(新MyClass);
)。它们用于禁止隐式转换,但您可以执行显式转换。就像使用
reset
,您必须明确地执行这些操作,以显示(并确保自己)对所做的事情非常确定

顺便说一句:来自原始指针的赋值也不起作用,因为
std::unique_ptr
没有将原始指针作为参数的重载赋值运算符。由于上述原因,原始指针不能隐式地转换为
std::unique_ptr
,因此移动赋值运算符(以
std::unique_ptr
为参数)也不会被考虑

我正在努力理解为什么
std::unique_ptr p=新MyClass
不起作用

正如@songyuanyao提到的,声明为
explicit
,说明您仍然可以在超过
explicit
的情况下初始化它:

// Valid, since now it's 'explicit'
std::unique_ptr<MyClass> p { new MyClass{} };
//有效,因为现在它是“显式的”
std::unique_ptr p{new MyClass{};

std::unique\u ptr
MyClass
不同,但是
std::unique\u ptr p;p、 重置(新MyClass);p=新的MyClass任务确定吗?这仍然是不允许的。我可以看出函数调用隐式构造函数是多么的危险。@starmole:因为它可能是偶然发生的。与意外键入“.reset()”相比,您更可能意外地将裸指针分配给
unique\u ptr
。请注意,在实际需要重新分配指针的情况下,您只需执行
p=std::unique\u ptr(新MyClass)即可或者,更好的是,如果您已经在C++14上,
p=std::make_unique()
@starmole是的,如果有一个
std::unique_ptr::operator=(T*)
将被调用。但请注意,这不仅有风险,而且毫无用处:无论如何,您不应该让原始指针四处浮动。创建唯一指针的惯用方法是
auto p=std::make_unique()
。在答复中这样说是有益的。