§ 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
?