When print(X x) is invoked, a copy of object x is generated(say x1), x1's member px points at same memory address of member px of the orginal object x. Thus when print returns, x1 is released and destructor ~x is excuted to delete px.
When statement X y(16); is excuted, its constructor allocates a new memory for its member px at the same address as in object x and stores 16 in it. Since the member px of object x keeps same address as in y, print(x) will print 16 and destroy memory px. Afterwards, when print(y) is excuted, since memory px is deleted, a random value is printed and then an error about deleting unexist memory is raised.
It seems not easy to be understood. But if you can understand it completely, I think you can improve your c/c++ skills a lot.