§ 3.10.1.5 of the standard defines prvalue expressions as:
- Prvalue ("pure" value of r) is the value of r, which is not the value of x. [Example: the result of calling a function whose return type is not a reference is prvalue. The value of a literal, such as 12, 7.3e5, or true, is also prvalue. - end of example]
So the foo() function is a prvalue expression:
class Foo {}; Foo foo() { return Foo{}; }
To initialize a lvalue reference to a non-volatile const type / rvalue reference , the initializer expression must be ( § 5.2.1.1 ):
[...] the value of xvalue (but not a bit field), the class prvalue, the value of the prvalue of an array, or the function lvalue and "cv1 T1" is compatible with "cv2 T2" or [...]
Thus,
Foo &&rrFoo_ = foo();
is a valid code, where rrFoo_ associated with a temporary object that extends the lifetime of the object ( §12.2 ):
Temporary classes of a class type are created in various contexts: binding a reference to a value (8.5.3), returning (6.6.3), a transformation that creates a prvalue (4.1, 5.2.9, 5.2.11, 5.4), throwing an exception (15.1) , and in some initializations (8.5).
As stated above and neglecting RVO, the next initialization of an object of type Foo will copy the movement of the temporary structure from the default object. A temporary object, which will then be used for copying, moves the construction of the final object named obj_foo :
Foo obj_foo{ foo() };
Thus, in both cases, we either sneak or even extend the lifetime of a temporary object that would otherwise be destroyed.
§3.10.1.2 defines x values as:
The value of x (the value of "eXpiring") also refers to the object, usually closer to the end of its life (so its resources can be moved, for example). [...]
I can not imagine the case when a temporary object is not created. So my question is: why are function expressions such as foo() considered a prvalue expression, even assuming they have at least similar properties, such as xvalues ?