为什么 std::unique_ptr 重置与赋值不同?
Why is std::unique_ptr reset not the same as assignment?
我正在尝试理解为什么
std::unique_ptr<MyClass> p = new MyClass;
不起作用,但是
std::unique_ptr<MyClass> p;
p.reset(new MyClass);
没问题。我有点理解它们的不同之处,但我想知道为什么选择让它们不同。 assignment 和 reset 不一样有什么危险?
首先,std::unique_ptr<MyClass> p = new MyClass;
不是赋值,是copy initialization. And it doesn't work because the 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
请注意 explicit
构造函数不在 copy initialization (eg std::unique_ptr<MyClass> p = new MyClass;
). You can use them in direct initialization 中考虑(例如 std::unique_ptr<MyClass> p (new MyClass);
)。它们用于禁止隐式转换,但您可以执行显式转换。就像 reset
的用法一样,你必须 明确地 做这些事情,以表明(并让你自己)你很确定你在做什么。
顺便说一句:原始指针的赋值也不起作用,因为 std::unique_ptr
没有将原始指针作为参数的重载赋值运算符。由于上述原因,原始指针不能隐式转换为std::unique_ptr
,因此移动赋值运算符(以std::unique_ptr
为参数)不会两者都考虑。
I am trying to understand why
std::unique_ptr<MyClass> p = new MyClass;
does not work
和@songyuanyao提到的一样的道理,这里声明explicit
,说明你仍然可以在超过explicit
的a different form of initialization中初始化它:
// Valid, since now it's 'explicit'
std::unique_ptr<MyClass> p { new MyClass{} };
我正在尝试理解为什么
std::unique_ptr<MyClass> p = new MyClass;
不起作用,但是
std::unique_ptr<MyClass> p;
p.reset(new MyClass);
没问题。我有点理解它们的不同之处,但我想知道为什么选择让它们不同。 assignment 和 reset 不一样有什么危险?
首先,std::unique_ptr<MyClass> p = new MyClass;
不是赋值,是copy initialization. And it doesn't work because the 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
请注意 explicit
构造函数不在 copy initialization (eg std::unique_ptr<MyClass> p = new MyClass;
). You can use them in direct initialization 中考虑(例如 std::unique_ptr<MyClass> p (new MyClass);
)。它们用于禁止隐式转换,但您可以执行显式转换。就像 reset
的用法一样,你必须 明确地 做这些事情,以表明(并让你自己)你很确定你在做什么。
顺便说一句:原始指针的赋值也不起作用,因为 std::unique_ptr
没有将原始指针作为参数的重载赋值运算符。由于上述原因,原始指针不能隐式转换为std::unique_ptr
,因此移动赋值运算符(以std::unique_ptr
为参数)不会两者都考虑。
I am trying to understand why
std::unique_ptr<MyClass> p = new MyClass;
does not work
和@songyuanyao提到的一样的道理,这里声明explicit
,说明你仍然可以在超过explicit
的a different form of initialization中初始化它:
// Valid, since now it's 'explicit'
std::unique_ptr<MyClass> p { new MyClass{} };