c++ 为什么unique_ptr有两个函数reset和operator=,它们做类似的事情,但没有重载?

mv1qrgav  于 2023-01-15  发布在  其他
关注(0)|答案(2)|浏览(118)

我知道这听起来可能是一个奇怪的问题,但我很好奇。unique_ptr operator=将一个r值引用作为参数,并调用reset(r.release()),然后移动自定义删除器。最后,operator返回 *this。

// this is pseudo code
unique_ptr& operator=(unique_ptr&& r)
{
  reset(r.release());  // Change managed pointer
  setDeleter(r.getDeleter());
  return *this;
}

unique_ptr reset函数将左值原始指针作为参数,并在更改其管理的指针后删除旧指针。在这两个函数之间,它们具有相同的更改所管理的指针的行为。并且该行为由同一个reset处理()函数。这两个函数做类似的事情,除了参数不同之外,我想不出有什么单独的用例。所以我想知道是否有可能让它们超载。比如:

// this is pseudo code
unique_ptr& operator=(unique_ptr&& r) // or a function named reset
{
  changeManagedPtr(r.release()); // and delete old pointer
  setDeleter(r.getDeleter());
  return *this;
}

unique_ptr& operator=(pointer p) // or a function named reset
{
  changeManagedPtr(p); // and delete old pointer
  // setDeleter(r.getDeleter()); there is no deleter in p
  return *this;
}

为什么这两个函数要分开写,而不是重载同名函数呢?如果可能的话,是不是可以使用一些不那么容易混淆的函数,比如:

unique_ptr<int> uniqPtrInt, dest;
int* rawPtrInt = new int;
dest = rawPtrInt;
// some work..
dest = uniqPtrInt;

我是不是假设错了?有没有我不知道的稳定性后果?

omqzjyyz

omqzjyyz1#

unique_ptr& unique_ptr::operator=(pointer p)可以实现,但委员会选择不实现,原因与他们明确unique_ptr::unique_ptr(pointer p)的原因相同。
unique指针表示对象的唯一所有权。如果你可以从原始指针隐式地构造或赋值它们,那么很容易意外地转移所有权(并且,在没有意识到你已经转移了所有权的情况下,做一些未定义的行为,比如双重删除)。

arknldoa

arknldoa2#

std::unique_ptr的赋值语义是move-only,即移动赋值。在此基础上添加一个从pointer看起来不透明的复制赋值,它在引擎盖下移动,可能会导致混乱,而std::unique_ptr的设计考虑到了安全性(“使其难以误用”)。这拒绝了用pointer重载来重载赋值运算符的想法。
超过reset():虽然reset()也可论证地提供重载以用std::unique_ptr重载的受管对象替换*this的受管对象,但这将意味着向std::unique_ptr的API添加本质上执行移动指派的另一方式,移动指派是其中移动指派操作应得到支持(语义上)的操作。

相关问题