Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is value returned by std::unique_ptr::get valid after moving unique_ptr?

Consider the following code snippet:

class Owner {
public:
 Owner(std::unique_ptr<int> ptr) : owned_pointer<int>(std:move(ptr)) {}
private:
 std::unique_ptr<int> owned_pointer;
};


std::unique_ptr<int> ptr(new int);
int* ptr1 = ptr.get();
Owner new_owner(std::move(ptr));

Is it safe to assume that ptr1 is valid as long as new_owner stays in scope? It seems to work, but I can't find a specification that states that explicitly - is it undefined behavior/implementation specific and just happen to work for me, or the code posted above is valid (ptr1 is guaranteed to point to moved pointer as long as it stays alive)?

like image 899
Ilya Kobelevskiy Avatar asked Apr 28 '15 14:04

Ilya Kobelevskiy


2 Answers

Yes, it is valid.

You can have multiple (plain) pointers pointing to the same object. The question is how long those pointers are valid or when the object pointed to is deleted.

A unique_ptr stores one more plain pointer and takes ownership, meaning it is responsible for when the object is destroyed. Moving it to another unique_ptr just transfers ownership, the object itself is still the same and all plain pointers pointing to it remain valid.

Only when the ownership is not transferred (or released) and the owning unique_ptr is destroyed, it also destroys the object. This would be the moment where all plain pointers pointing to the object become dangling pointers and dereferencing them would be illegal.

like image 102
Daniel Frey Avatar answered Oct 06 '22 21:10

Daniel Frey


Yes, the C++11 specification guarantees that transferring ownership of an object from one unique_ptr to another unique_ptr does not change the location of the object itself, and that get() on the second unique_ptr returns the same as it would have on the first unique_ptr before the transfer.

Looking at N3337, section 20.7.1:

  1. Additionally, u 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.

where u is a unique_ptr object that stores a pointer u.p.

The first bullet answers the question directly, since get() is specified as returning the u.p.

like image 24
mgiuffrida Avatar answered Oct 06 '22 21:10

mgiuffrida