I was experimenting with using unique_ptr and wrote some simple code to check how it works with move semantics.
#include <iostream>
#include <vector>
using namespace std;
class X
{
public:
X(){}
~X() { cout << "Destructor X" << endl; }
void Print() { cout << "X" << endl; }
};
int main()
{
unique_ptr<X> ptr(new X());
ptr->Print();
vector<unique_ptr<X>> v;
v.push_back(move(ptr));
ptr->Print();
v.front()->Print();
return 0;
}
The output is as follows:
X
X
X
Destructor X
My expectation was that the original unique_ptr ptr would be invalidated after the push_back. But the Print() method is called just fine. What would be the explanation for this behavior?
What you have is plain undefined behavior. If I replace the contents of
main
with the followingBoth gcc and clang still print
You're calling a member function on a
nullptr
, and I'm guessing it just happens to work because the member function doesn't actually make use of thethis
pointer. Change your class definition to:Now your original code should result in a segmentation fault because it'll attempt to dereference
nullptr
.As for your expectation that
unique_ptr
will be invalidated after you move from it, you're absolutely correct. This is guaranteed by the standard.§20.8.1/4 [unique.ptr]
Above
u
&u2
areunique_ptr
objects, andp
is the pointer to the managed object.It's set to a null pointer. You can check that by comparing it to
nullptr
.You're calling a member function on a null pointer, which is undefined behaviour. That member function doesn't actually access any data in the class, so it doesn't crash, but it's still undefined behaviour.
You get similar behaviour for this program, it has nothing to do with
unique_ptr
:It appears to work fine because
X::Print()
doesn't actually read anything from thethis
pointer. If you change the definition ofX::Print()
to access some member data in the class you'll probably get a crash due to dereferencing a null pointer.See When does invoking a member function on a null instance result in undefined behavior? for more information.