Whether Should We Call std::move on std::unique_ptr

If a function takes a std::unique_ptr<>, that means it takes ownership of the argument. Callers need to use std::move() to indicate that they’re passing ownership if the object being passed is not a temporary:

// Foo() takes ownership of |bar|.
void Foo(std::unique_ptr<Bar> bar);

...
std::unique_ptr<Bar> bar_ptr(new Bar());
Foo(std::move(bar_ptr));          // After this statement, |bar_ptr| is null.
Foo(std::unique_ptr<Bar>(new Bar()));  // No need to use std::move() on temporaries. You can do so but it prevents copy elision

If a function returns a std::unique_ptr<>, that means the caller takes ownership of the returned object. Usage of std::move() while returning an object is only needed if the return type of the function differs from the type of the local variable.

class Base { ... };
class Derived : public Base { ... };

// Foo takes ownership of |base|, and the caller takes ownership of the returned
// object.
std::unique_ptr<Base> Foo(std::unique_ptr<Base> base) {
  if (cond) {
    return base;                           // Transfers ownership of |base| back to
                                           // the caller.
  }

  // Note that on these next codepaths, |base| is deleted on exit.
  if (cond2) {
    return std::unique_ptr<Base>(new Base()));  // No std::move() necessary on temporaries.
  }
  std::unique_ptr<Derived> derived(new Derived());
  return std::move(derived);               // Note that std::move() is necessary because
                                           // type of |derived| is different from the return
                                           // type of the function.
}

Leave a Reply

Your email address will not be published. Required fields are marked *