Ok, so I've been learning about lvalues and rvalues - could somebody well versed in C/C++ tell me if my thinking is correct?
Consider the code:
int i = 3;
int j = i;
Here we have two lvalues i
and j
, when i
is assigned to j
it becomes an implicit rvalue because a copy of i
is stored in j
. If however the code looked like:
int i = 3;
int j = &i;
Would both j
and &i
be lvalues because they are both physical addresses in memory? The way I understand it is that rvalues are temporary data, whereas lvalues have a physical/referenceable memory address.
Any clarification on this would be great!
The variable i
never stops being an lvalue. If you can apply the address-of operator to something (like you do in the second example) then it's an lvalue.
Also in the second example &i
is a pointer to i
, and has the type int*
. You have a type mismatch there between the declaration of j
and the value you want to initialize it with.
Lastly, while i
by itself is a lvalue the expression &i
is not an lvalue, because you can't apply the address-of operator to it (i.e you can't do &&i
).
Here we have two lvalues
i
andj
Yep
when
i
is assigned toj
it becomes an implicit rvalue because a copy ofi
is stored inj
Not really, i
is still an lvalue, but it's converted to an rvalue to read its value. This is called an lvalue-to-rvalue conversion. j
is still an lvalue.
Would both
j
and&i
be lvalues because they are both physical addresses in memory?
j
is an lvalue, but &i
is an rvalue; specifically a prvalue of type int*
.
Being an lvalue or an rvalue is a property of an expression. Generally, all expressions which constitute a non-const qualified identifier are modifiable lvalues:
int i = 5;
i; // the expression "i" is an lvalue and is modifiable
const int j = 3;
j; // the expression "j" is still an lvalue, but not modifiable
An lvalue expression (unless qualified with const
) can be modified through any of the assignment, ++
or --
operators. You can also apply the &
"address-of" operator on such an expression.
Some operators like the unary *
, the array subscript operator []
, and the .
and ->
operators also yield lvalues. This means that you can say, for example, *p = 3
, or a[i] = 5
, or b.c++
or &c->d
.
On the other hand, expressions which are not lvalues are rvalues (they are temporary and cannot be modified). If you write something like 3 = 5
or 7++
, the compiler will complain that the 3
and 7
subexpressions are not lvalues.
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