Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to unique_ptr after std::move()?

Tags:

c++

unique-ptr

This code is what I want to do:

Tony& Movie::addTony() {     Tony *newTony = new Tony;     std::unique_ptr<Tony> tony(newTony);     attachActor(std::move(tony));     return *newTony; } 

I am wondering if I could do this instead:

Tony& Movie::addTony() {     std::unique_ptr<Tony> tony(new Tony);     attachActor(std::move(tony));     return *tony.get(); } 

But will *tony.get() be the same pointer or null? I know I could verify, but what is the standard thing for it to do?

like image 747
user3496846 Avatar asked Mar 17 '16 20:03

user3496846


People also ask

What happens when you to std :: move?

std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.

Does unique_ptr delete itself?

unique_ptr objects automatically delete the object they manage (using a deleter) as soon as they themselves are destroyed, or as soon as their value changes either by an assignment operation or by an explicit call to unique_ptr::reset.

Does std :: move do anything?

std::move is actually just a request to move and if the type of the object has not a move constructor/assign-operator defined or generated the move operation will fall back to a copy.

Can I use object after std :: move?

In general, it is perfectly safe to assign to an object that has been an argument to std::move . (A particular class might cause an assertion, but that would be a very odd design.)


2 Answers

No, you cannot do that instead. Moving the unique_ptr nulls it. If it didn't, then it would not be unique. I am of course assuming that attachActor doesn't do something silly like this:

attachActor(std::unique_ptr<Tony>&&) {     // take the unique_ptr by r-value reference,     // and then don't move from it, leaving the     // original intact } 

Section 20.8.1 paragraph 4.

Additionally, u (the unique_ptr object) can, upon request, transfer ownership to another unique pointer u2. Upon completion of such a transfer, the following postconditions hold:
   -- u2.p is equal to the pre-transfer u.p,
   -- u.p is equal to nullptr, and
   -- if the pre-transfer u.d maintained state, such state has been transferred to u2.d.

like image 195
Benjamin Lindley Avatar answered Oct 01 '22 02:10

Benjamin Lindley


The standard says (§ 20.8.1.2.1 ¶ 16, emphasis added) that the move constructor of std::unique_ptr

unique_ptr(unique_ptr&& u) noexcept; 

Constructs a unique_ptr by transferring ownership from u to *this.

Therefore, after you move-construct the temporary object that gets passed as argument to attachActor form your tony, tony no longer owns the object and hence tony.get() == nullptr. (This is one of the few cases where the standard library actually makes assertions about the state of a moved-away-from object.)

However, the desire to return the reference can be fulfilled without resorting to naked new and raw pointers.

Tony& Movie::addTony() {   auto tony = std::make_unique<Tony>();   auto p = tony.get();   attachActor(std::move(tony));   return *p; } 

This code assumes that attachActor will not drop its argument on the floor. Otherwise, the pointer p would dangle after attachActor has returned. If this cannot be relied upon, you'll have to re-design your interface and use shared pointers instead.

std::shared_ptr<Tony> Movie::addTony() {   auto tony = std::make_shared<Tony>();   attachActor(tony);   return tony; } 
like image 33
5gon12eder Avatar answered Oct 01 '22 03:10

5gon12eder