Objects exist in memory at runtime. They can be temporary (if constructed in a certain manner) or not.
Expressions are parts of the source code referring to objects, they only exist at compile-time. They can be lvalues or rvalues.
Multiple expressions can refer to the same object, and have different values categories (lvalue vs rvalue).
Yes, an expression that creates a temporary is (always?) an rvalue, but that doesn't mean you can't get an lvalue expression referring to the same object.
obj.f()
indeed creates a temporary A
object, and this expression is an rvalue. But the a
expression in return a;
is an lvalue regardless.
In general, all "names" are lvalues, for safety reasons. If a
was a class for which copying and moving behave differently, and you did auto x = a, y = a;
, this would break if a
was an rvalue. (There are exceptions to this rule, such as local variables being implicitly moved in return
statements.)