Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are function expressions returning non-reference types considered to be prvalues and not xvalues?

Tags:

People also ask

Can a function return an lvalue?

Why is it not possible to set a function returning an address while it is possible to set a function that returns a reference. Short answer: You return a pointer by-value and anything returned by-value is (by definition) not an lvalue.

Is a function a reference type?

The types can be divided into two groups: primitive types and reference types. Numbers, boolean values, and the null and undefined types are primitive. Objects, arrays, and functions are reference types.

What is a glvalue?

A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function. A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears.

Can rvalue be modified?

rvalue of User Defined Data type can be modified. But it can be modified in same expression using its own member functions only.


§ 3.10.1.5 from the standard defines prvalue expressions as:

— A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a function whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is also a prvalue. — end example ]

Thus the function foo() 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 has to be ( § 5.2.1.1 ) :

[...] an xvalue (but not a bit-field), class prvalue, array prvalue or function lvalue and “cv1 T1” is reference-compatible with “cv2 T2”, or [...]

Thus,

Foo &&rrFoo_ = foo(); 

is valid code where rrFoo_ binds to a temporary object extending the lifetime of the object (§12.2):

Temporaries of class type are created in various contexts: binding a reference to a prvalue (8.5.3), returning a prvalue (6.6.3), a conversion 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 following initialization of an object of type Foo will copy move construct a temporary from default constructed object. The temporary object which will then be used to copy move construct the final object named obj_foo :

Foo obj_foo{ foo() }; 

So in both cases we either steal from or even extend the lifetime of the temporary object, which would otherwise be destroyed.

§3.10.1.2 defines xvalues as:

An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). [...]

I cannot think of any case where a temporary object isn't created. So my question is, why are function expressions like foo() are considered to be prvalue expression even thought they have at least similar properties as xvalues ?