3

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?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
user1086635
  • 1,536
  • 2
  • 15
  • 21

5 Answers5

4

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.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Hello. Related: `int m = *pn; // indirection + lvalue-to-rvalue conversion` [cppreference](https://en.cppreference.com/w/cpp/language/operator_member_access). I don't get where rvalue is in this statement?? `*pn` is not an rvalue because I can put `*pn = 3;`. – bloody Dec 17 '22 at 19:32
2

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.

Sebastian
  • 8,046
  • 2
  • 34
  • 58
  • I didn't downvote. why do you think `&x` is rvalue? The other two answers by @Nawaz and @Kerrek seems to disagree with you. – user1086635 Dec 13 '11 at 12:17
  • When `*p` stores an address and `&x` is the address of `x` then i assume this is an rvalue since this value itself has no address and can't be an lvalue. Or am i wrong? The cited C++ excerpt say's that i am, but then this makes no sense for me. – Sebastian Dec 13 '11 at 12:33
  • I think you're correct. From what I understood, `&x` doesn't make `x` an rvalue because its just the address of x which is considered an rvalue. +1. – user1086635 Dec 13 '11 at 13:04
  • Hello. What about this: `int m = *pn; // indirection + lvalue-to-rvalue conversion` [cppreference](https://en.cppreference.com/w/cpp/language/operator_member_access). I don't get where rvalue is in this statement?? `*pn` is not an rvalue because I can put `*pn = 3;`. – bloody Dec 17 '22 at 19:41
1

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;
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • "_int(10) and A() are rvalue expressions, for they create temporary objects._" `int(10)` does _not_ create a temporary object. – curiousguy Dec 25 '11 at 16:05
  • @curiousguy: It does. End of the discussion. – Nawaz Dec 25 '11 at 17:36
  • @Nawaz "_It does._" In which language? – curiousguy Dec 25 '11 at 17:43
  • @curiousguy: Quote from the language in which it doesn't. – Nawaz Dec 25 '11 at 18:22
  • @curiousguy: Are those "quotations" from the language? I asked you to quote from the language. – Nawaz Dec 26 '11 at 03:38
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/6131/discussion-between-curiousguy-and-nawaz) – curiousguy Dec 26 '11 at 03:56
  • @curiousguy: You've never quoted from the language specification. You explain something which is not in the spec. – Nawaz Feb 18 '12 at 05:11
  • @curiousguy: If you claim something (and at the same time, * intellectually honest*), you would tell me the reference from spec, supporting your claim. – Nawaz Feb 18 '12 at 05:30
  • @curiousguy: which means you don't know what you're talking about. – Nawaz Feb 18 '12 at 05:58
  • @curiousguy: For God's sake, you really can't give me the reference? – Nawaz Feb 18 '12 at 06:09
  • @curiousguy: The section is too big. Quote statement(s) which support your stance, then I will believe. – Nawaz Feb 18 '12 at 06:13
  • Can **you** give me the reference where it is said that a `int` rvalue can refer to a temporary of type `int`? – curiousguy Feb 18 '12 at 06:14
  • @curiousguy: If there are no temporaries of non-class type, then what does `int const & x = 5` do? And what would `std::cout << &x << std::endl` print? – Nawaz Feb 18 '12 at 06:19
0

"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).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

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.

Community
  • 1
  • 1
curiousguy
  • 8,038
  • 2
  • 40
  • 58