Why are function expressions returning not reference types considered prvalues ​​and not xvalues?

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

+6
source share
1 answer

Given int f1() and int && f2() , he assumed that decltype(f1()) is int , and decltype(f2()) is int && . The way this is done for the job is to indicate that f1() is a prvalue, and f2() is the value of x. decltype then checks to see if the expression is prvalue, xvalue, or lvalue. If f1() and f2() were both x values, the same difference still had to be made in a different way.

+2
source

Source: https://habr.com/ru/post/1014703/


All Articles