Why does std :: move () from unique_ptr from the <unique_ptr> list really move it?
using Ptr = std::unique_ptr<int>;
Ptr f(bool arg) {
std::list<Ptr> list;
Ptr ptr(new int(1));
list.push_back(std::move(ptr));
if (arg) {
Ptr&& obj1 = std::move(list.front());
// Here |obj1| and |list.front()| still point to the same location!
list.pop_front();
return std::move(obj1);
}
else {
Ptr obj2 = std::move(list.front());
list.pop_front();
return obj2;
}
};
Ptr&& ptr1 = f(true); // |ptr1| is empty.
Ptr&& ptr2 = f(false); // |ptr2| is fine.
Full source here .
I do not understand - why obj1and list.front()still point to the same place after the call std::move()?
You have a link to the std::unique_ptrinside list.
Ptr&& obj1 = std::move(list.front());
// ^^ THIS
So when you do
list.pop_front();
The unique pointer that is listdestroyed, and you are left with a saggy reference to some object that is already destroyed, which is illegally used, returning it from the function.
UPDATE: std::move std::unique_ptr. std::move , , r- . , :
Ptr&& obj1 = std::move(list.front());
assert(obj1.get() == list.front().get());
else , .
Ptr obj2 = std::move(list.front());
list.pop_front(); // OK; destroys the moved-from unique_ptr
return obj2; // OK; obj2 points to something valid and is not a dangling reference
move-semantics std::unique_ptr . move-semantics .
list.push_back(std::move(ptr)); ptr nullptr ( ).
, arg , list.front() , std::move r-value r-value obj1. , , r-value . r- - , , .
, cout,
Ptr& obj1 = list.front();
, rj- obj1, , ,
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
, ,
Ptr obj1 = std::move(list.front());
(, , nullptr-ify ) obj1.
, ,
list.pop_front();
unique_ptr r-value undefined. ( ).