unique_ptr operator=

10
std::unique_ptr<int> ptr;
ptr = new int[3];                // error
错误 C2679: 二元 '=' :没有找到接受右侧操作数类型为 'int *' 的运算符(或者没有可接受的转换方式)。
为什么这不能编译?如何将本地指针附加到现有的unique_ptr实例?
2个回答

29

首先,如果您需要一个唯一的数组,请创建它

std::unique_ptr<int[]> ptr;
//              ^^^^^

这样可以让智能指针正确使用delete[]来释放指针,并定义operator[]以模仿普通的数组。


然后,operator=仅为独占指针的右值引用定义,而不是原始指针,原始指针无法隐式转换为智能指针,以避免意外赋值打破独占性。因此,无法直接将原始指针分配给智能指针。正确的方式是将其放入构造函数中:

std::unique_ptr<int[]> ptr (new int[3]);
//                         ^^^^^^^^^^^^

或者使用 .reset 函数:

ptr.reset(new int[3]);
// ^^^^^^^          ^

或者明确地将原始指针转换为唯一指针:

ptr = std::unique_ptr<int[]>(new int[3]);
//    ^^^^^^^^^^^^^^^^^^^^^^^          ^

如果你可以使用C++14,请优先使用make_unique函数来代替完全使用new

ptr = std::make_unique<int[]>(3);
//    ^^^^^^^^^^^^^^^^^^^^^^^^^^

2
原因是operator=不接受int*,而接受int*的构造函数被标记为explicit(对于std::unique_ptr<int>std::unique_ptr<int[]>都是如此)。然而,operator=作为移动赋值运算符而不是复制赋值运算符与此无关。 - Luc Danton
@LucDanton:好的,已更新以包括此内容。 - kennytm

2

以下是对来自KennyTM的回答的补充(自C++11起)

 tr = (decltype(tr)(new int[3]));

个人而言,我更喜欢这种方式,因为它使得更新类型更加容易。(只需要在一个地方进行更新)


这个调用不会使用 delete[] 而是 delete,从而产生未定义的行为,对吗? - Jimmy R.T.

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