Home > Blockchain >  Why do unique_ptr have two functions reset and operator= that do similar things but not overload?
Why do unique_ptr have two functions reset and operator= that do similar things but not overload?

Time:01-12

I know this may sound like a strange question, but I'm very curious. unique_ptr operator= takes an r-value reference as a parameter and calls reset(r.release()), then move custom deleter. finally, operator returns *this. like:

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

unique_ptr reset function takes l-value raw pointer as a parameter and delete the old pointer after changing the pointer it manages. Between the two, they have the same behavior of changing the pointer being managed. And that behavior is handled by the same reset() function. These two functions do similar things, and I couldn't think of a separate use case other than the difference in parameters, so I wondered if it might be possible to overload them. like:

// 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;
}

Why are the two functions written separately and not as overloaded functions with the same name? If it were possible, wouldn't it be possible to use something less confusing like this:

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

Am I assuming something wrong? Are there any stability ramifications that I'm not aware of?

CodePudding user response:

unique_ptr& unique_ptr::operator=(pointer p) can be implemented, but the committee chose not to, for the same reason that they made unique_ptr::unique_ptr(pointer p) explicit.

A unique pointer represents unique ownership of an object. If you could implicitly construct or assign them from raw pointers, it would be very easy to accidentally transfer ownership (and, not realising that you have, do something with undefined behaviour, like double delete).

CodePudding user response:

The assignment semantics of std::unique_ptr is move-only, i.e. move assignment. Adding onto that an opaque copy-assignment-looking from pointer which moves under the hood would arguably risk leading to confusion, and std::unique_ptr was designed with safety in mind ("make it hard to misuse"). That rejects the idea of overloading the assignment operator with a pointer overload.

Over to reset(): whilst reset() could arguably also provide an overload to replace the managed object of *this with that of a std::unique_ptr overload, it would mean adding to the API of std::unique_ptr another way of essentially performing move-assignment, an operation where move-assignment op should be favored (semantically).

  • Related