Is it necessary to have a temporary or a literal to have an rvalue?

自古美人都是妖i 提交于 2019-12-11 08:13:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!