Question

This question asks if all temporaries are rvalue.

The answer is no, because if we consider this expression:

const int &ri = 2 + 3;

then, the very same temporary (2 + 3), which is an rvalue here, can be used as an lvalue in a subsequent expression:

const int *pi = &ri;

so this temporary is not (only) an rvalue.

The logic statement temporary ==> rvalue is then false.

However, we cannot write

const int &ri = &(2 + 3); // illegal, 2 + 3 -> temporary -> rvalue

or

int *i = &4; // illegal, 4 is an rvalue (literal)

or

int foo();
int *i = &foo(); // illegal, foo() -> temporary -> rvalue

Thus my question is, can we generate an rvalue in a certain expression without having a temporary or a literal? Is rvalue ==> (temporary or literal) true?

Was it helpful?

Solution

Expressions that yield temporary objects are r-values. There's a special rule which allows const-references and r-value references to bind to r-values, and this extends the lifetime of the temporary object to that of the reference (see 12.2(5)), but that does not make the temporary-object expression any less of an r-value.

However, once bound to a reference, the reference variable itself has a name, and thus the reference expression is an l-lvalue.

Don't confuse expressions, variables and objects.

OTHER TIPS

The rvalue and lvalue attributes apply to expressions, not to objects. An expression can be either an lvalue or an rvalue. Oversimplifying a expression that yields a value is an rvalue-expression and an expression that yields an object is an lvalue-expression. The lvalue to rvalue conversion is the act of reading the value out of an object.

A expression that yields a temporary and a literal are both rvalue-expressions they represent a value not an actual object.

In your example:

const int &ri = 2 + 3;
const int *pi = &ri;

The expression 2+3 is an rvalue-expression used to initialize a constant reference. That, according to the language implies the extension of the lifetime of the temporary beyond the current expression and until the reference goes out of scope. After that, in the second expression, the subexpression ri is an lvalue-expression that refers to the temporary object, whose lifetime has been extended.

Note that there are other ways of creating rvalue expressions with temporaries, for example calling a member that yields a reference:

struct test {
   test& thisTest() { return *this; }
};
test foo();
... foo().thisTest()

The subexpression foo() is an rvalue-expression, but the expression foo().thisTest() is an lvalue-expression. Both of them refer to a temporary object that will disappear at the end of the full expression.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top