A lot of people are confused when they hear that in
int&& x
x
is an rvalue reference and x
is an lvalue. Misunderstanding stems from the fact that identifiers and expressions are different things, and so are types and value categories. Moreover, types of expressions are "adjusted prior to any further analysis", and the words "rvalue" and "lvalue" can appear both in type name and in value category name.
I want to clarify formal definitions. Suppose we have a function:
void f(int&& x) {
... = x;
... = std::move(x);
}
Are the following statements correct?
- In the line 1,
x
is an identifier (id-expression) that names a function parameter. Its type isint&&
, and this is the type thatdecltype(x)
returns.x
is not an expression and has no value category. - In the line 2,
x
is an expression. Before type adjustment its type isint&&
, and after the type becomesint
. The value category is lvalue. - In the line 3,
std::move(x)
is an expression. Its type before adjustment isint&&
, after -int
. The value category is xvalue. - When we say that
x
has rvalue reference type, we refer either to the type ofx
as an identifier, or to the type ofx
as an expression before type adjustment. - The word "type" in the statement "Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories" at cppreference.com refers to the type after type adjustment.
- When Scott Meyers writes "If the type of an expression is an lvalue reference (e.g.,
T&
orconst T&
, etc.), that expression is an lvalue." he refers of the type before adjustment, and the second word "lvalue" refers to the value category.
Aucun commentaire:
Enregistrer un commentaire