Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what are the differences between std::move and unique_ptr::reset?

For std::unique_ptrs p1 and p2, what are differences between std::move() and std::unique_ptr::reset()?

p1 = std::move(p2);

p1.reset(p2.release());
like image 293
hhbilly Avatar asked Dec 13 '12 12:12

hhbilly


People also ask

What does Unique_ptr Reset do?

unique_ptr::resetReplaces the managed object. 1) Given current_ptr , the pointer that was managed by *this, performs the following actions, in this order: Saves a copy of the current pointer old_ptr = current_ptr. Overwrites the current pointer with the argument current_ptr = ptr.

What happens when you move a Unique_ptr?

A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it.

What is std :: Unique_ptr?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.


2 Answers

The answer should be obvious from the standard's specification of move assignment in [unique.ptr.single.assign]/2:

Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by an assignment from std::forward<D>(u.get_deleter()).

Clearly move assignment is not the same as reset(u.release()) because it does something additional.

The additional effect is important, without it you can get undefined behaviour with custom deleters:

#include <cstdlib>
#include <memory>

struct deleter
{
  bool use_free;
  template<typename T>
    void operator()(T* p) const
    {
      if (use_free)
      {
        p->~T();
        std::free(p);
      }
      else
        delete p;
    }
};

int main()
{
  std::unique_ptr<int, deleter> p1((int*)std::malloc(sizeof(int)), deleter{true});
  std::unique_ptr<int, deleter> p2;
  std::unique_ptr<int, deleter> p3;

  p2 = std::move(p1);  // OK

  p3.reset(p2.release());  // UNDEFINED BEHAVIOUR!
}
like image 189
Jonathan Wakely Avatar answered Oct 17 '22 06:10

Jonathan Wakely


The first one is capable of warning you if there is a destructor mismatch, for example. In addition, release() is a very dangerous function, and your trivial example is correct but many other uses are not. It's best to simply never, ever use this function.

like image 31
Puppy Avatar answered Oct 17 '22 07:10

Puppy