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.
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.
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.
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
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With