if it did cast it into an rvalue equivalent then shouldn't obj's dtor be called after the end of expression at (a) above just like what happens to the more natural rvalue at (b) ?
Ya, I'm confused. What does casting a plain object to a reference (lvalue or rvalue) actually mean? I'm unable to grasp that. A reference is supposed to behave exactly as that object right ? And the user should not be able to tell the difference. So casting to rvalue reference should make it behave exactly like an rvalue, no? And therefore be destroyed at the end of that expression.
Expressions can be l-/r-/x-values, but cannot have a reference type
Objects cannot be l-/r-/x-values, and cannot have a reference type
Variables cannot be l-/r-x-values and can have a reference type.
std::move does not cast "a plain object": its argument is an expression, which, in your case, is the lvalue expression "obj" whose type is ClassA.
The result of std::move is an xvalue expression, whose type is ClassA. Since it's an xvalue, it can be used to initialize an rvalue reference variable, with ClassA&& r = std::move(obj);