Without move-semantics std::unique_ptr
is less useful. With move-semantics it allows transfer of ownership to another object.
With list.push_back(std::move(ptr));
you're transferring the ownership of the data to a new element and leaving ptr in a nullptr state (read here).
After that, if arg is true, since list.front()
returns a reference to the first element in the container, std::move
takes an r-value out of it and feeds it to the r-value reference obj1. Notice that you're not transferring ownership to another object since you're only asking for a r-value reference to the data. An r-value reference is, in the end, a reference to a value.
In the specific case above, regarding the cout statement, it is equivalent to getting just a simple reference to the object
Ptr& obj1 = list.front();
Now you have both the element into the list and the obj1 r-value reference "pointing" to the same data and modifying one will cause modifying both
Ptr&& obj1 = std::move(list.front());
std::cout << obj1.get() << std::endl << list.front().get() << std::endl; // same address
obj1.reset(new int(2));
std::cout << obj1.get() << std::endl << list.front().get() << std::endl; // same other address
if you were, as in the false case, to do
Ptr obj1 = std::move(list.front());
then you would have had the ownership (and thus the nullptr-ify of the list object) transfer to obj1.
If you followed the above reasoning, you can also realize that the line
list.pop_front();
destroyes the unique_ptr object and leaves the r-value reference into an undefined state. You shouldn't really be returning it (and using it).