3
votes

C++ Standard (4/5) the lvalue-to-rvalue conversion is not done on the operand of the unary & operator.

For example:

int x;
int *p = &x;

In the above case, are p are &x both lvalues? or What would be an appropriate example?

Edit:

What about this?

int &r = x;

I'm sure there will be no conversion in this statement, but i'm confused how does & operator involve in this?

5
there is also an x value. I think the &x is rvalue in the aboveBЈовић
@VJovic: Yes, but this is not about C++11 :P.user1086635
Ok, then never mind the commentBЈовић
There is no & operator in your second example.Puppy

5 Answers

4
votes

The quote says that the conversion is not applied on the operand of unary & (in this case, x). So the operand of & is an lvalue.

This is different from, say, the unary + operator. If you write +x, then lvalue-to-rvalue conversion is applied to the sub-expression x (with undefined behavior in this case, since x hasn't been initialized).

Informally, "lvalue-to-rvalue conversion" means "reading the value".

The quote doesn't say anything about the result of &, which in fact is an rvalue. In int *p = &x;:

  • x is an lvalue, referring to the variable of that name,
  • &x is an rvalue, it's part of the initializer (specifically, an assignment-expression),
  • p is neither an rvalue nor an lvalue, because it is not a (sub-)expression. It's the name of the variable being defined. In the C++ declarator grammar it's the declarator-id (8/4 in the C++03 standard).

int &r = x; doesn't use the & address-of operator at all. The & character in the declarator is just the syntax meaning that r is a reference-to-int, it's not taking the address of r. In the C++ declarator grammar, it's actually called the ptr-operator.

2
votes

Think of lvalue as storage place and of rvalue as the value to store there. Therefore *p is lvalue and &x is rvalue. However, & requires an lvalue as operand (x) but the result is a rvalue, but this does not change x itself.

1
votes

The Standard quote basically says the operand on which & applies, doesn't become rvalue. It remains lvalue.

In fact, the operand of & cannot be rvalue. It has to be lvalue, otherwise one would be able to get the address of a temporary object which is not allowed by the Standard:

struct A{};

int *addressOfTemporary_int_object = &(int(10)); //error
A *addressOfTemporary_A_object = &A(); //error

It is precisely because the operand of & has to be lvalue, the above expressions are illegal, as the subexpressions int(10) and A() are rvalue expressions, for they create temporary objects.

Also note that even though the subexpression x in the expression &x is an lvalue, the result of applying & on x is an rvalue. That is, the expression &x is an rvalue, and cannot appear on the right side of assignment operator:

&r = whatever; //illegal

I hope this helps you understanding the quote.


What about this?

int &r = x;

This is okay. Here & makes r a reference of object x. The & is not an operator here, and is not associated with the reference r, rather it is associated with the type. It is less confusing to write this as:

int&  r = x;

//Or if you use typedef as
typedef int& intref;
intref r = x;
0
votes

"On the operand" should refer to the x on the right-hand-side. That is, the subexpression x in the statement int *p = &x; is not an rvalue, but rather an lvalue. Contrast this to int a = b;, where the subexpression b is an rvalue (after conversion).

0
votes

C++ Standard (4/5) the lvalue-to-rvalue conversion is not done on the operand of the unary & operator.

This quote is there just to confuse you. It has no other purpose. ;)

The most important quote is (quoting N3242, so the new terminology has "prvalue" instead of rvalue):

Whenever a glvalue expression appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue (4.1), array-to-pointer (4.2), or function-to-pointer (4.3) standard conversions are applied to convert the expression to a prvalue.

So the language could be described in term of constructs which expect a prvalue and constructs which do not. In particular, operator & does not "expect a prvalue" (quite the contrary), so the lvalue-to-rvalue implicit conversion is not necessary and won't be applied.

The standard description is not consistent: it never explicitly says that in x += y, the lvalue-to-rvalue implicit conversion is not applied to x, presumably because it extremely obvious. Why the authors felt the need to explicitly say that for &x, where it is equaly obvious, is beyond me.

I think these mentions that implicit conversions are not applied should be removed. The standard describe what happens, not the (infinitely many) things that do not happen (unless it is extremely surprising that it does not happen).

Implicit conversions are applied only to adjust the "nature" of an expression to the expectation of the context (context can be an expression, statement, declaration, ctor-init-list...).

What about this?

int &r = x;

I'm sure there will be no conversion in this statement,

because no implicit conversion is needed here. Implicit conversion are applied only when needed. Reference binding does not expect a rvalue.

but i'm confused how does & operator involve in this?

It is not.