问题
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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/13205043/is-it-necessary-to-have-a-temporary-or-a-literal-to-have-an-rvalue