Let's start here:
modify1(move(t_mv1));
For constructing the parameter of modify1
, the move constructor of T
is used:
T(T &&t){
*this = move(t); // <--- this calls move assignment operator
};
Note the commented line above. By that time, the two data members of *this
object are default initialized, which for pointers means they're left with an indeterminate value. Next, the move assignment operator is called:
T& operator=(T &&lhs){
swap(this->a, lhs.a); // reads indeterminate values and invokes
swap(this->b, lhs.b); // undefined behaviour
return *this;
};
Now when modify1
returns, the parameter object gets destroyed and the destructor of T
calls delete
on uninitialized pointers, again invoking undefined behaviour
I haven't looked in the second part (with modify3
), but I suspect something similar is going on.