Evaluation of a reference expression
Asked Answered
B

2

2

As per @Potatoswatter's suggestion, I have created a new discussion.

Reference is this response from @Potatoswatter

Given the code snippet,

int i = 3, &j = i; 
j = ++ i;

The comment which I seek clarity on, is this. (which seems to be an important missing piece in my understanding of the unsequenced evaluation a.k.a sequence point):

@Chubsdad: Even though it's an alias, its glvalue evaluation does not require a glvalue evaluation of i. Generally speaking, evaluating a reference does not require the original object to be on hand. There's no reason it should be UB, so it makes sense there should be an easy loophole or transformation to code which is not UB.

and

The reference doesn't tell the compiler to go look at the referenced variable and get its lvalue, because it might not know what variable is referenced. The compiler computes the lvalue of the reference and that lvalue identifies an object. If you want to debate this further, please open a new question.

Any possible lack of clarity in the question is part of the 'undefined behavior' I am going through trying to understand 'unsequenced evaluation', 'sequence point' etc in C++0x.

Barnette answered 6/10, 2010 at 7:10 Comment(1)
Just to patch up the first statement, by "on hand" I mean "statically determined." By "transformation to code which is not UB" I mean the process of taking code which is UB due to side effects on lvalue objects which are not subsequently evaluated as rvalues, such as i = ++ i, and introducing reference variables (j here) to duplicate such lvalues so their evaluation is not nominally affected by side effects.Silence
H
2

Imagine the following

int &i = *new int;

If you say that i is an alias for another name - what name? A reference either references an object or function. When you say "glvalue", you refer to a property of a particular expression, not to a property of an object.

int i = 0;
int &ri = i;

Now, i is an lvalue expression and ri is an lvalue expression too (both of the syntactic category id-expression). They name (as found by name-lookup) a reference and an int variable.

If you now determine the object identity for the ri case, you need to take the reference and make the expression refer to the object it was initialized with. This is called an lvalue evaluation because you determine the property of an lvalue (i.e the referent).

You need to do the same for the i case. I.e you figure out to what object the lvalue expression i refers to. A glvalue evaluation of ri thus is different than glvalue evaluation of i, despite both of them yielding the same result.

Rvalue evaluation means to take an lvalue and apply the lvalue to rvalue conversion. In other words, to read a value.

Harriman answered 6/10, 2010 at 19:31 Comment(2)
So is this statement still correct (as in OP)? (The reference doesn't tell the compiler to go look at the referenced variable and get its lvalue, because it might not know what variable is referenced)Barnette
@Barnette "Variable" means "named object". As I showed above, a reference can refer to an unnamed object. I think he means with that statement that a reference isn't like a "link into the symbol table of the compiler", but more like a pointer as in "reference to an address".Harriman
R
1

Conceptually, a reference in C++ is an alias, or alternative name, for some object. It is this concept that should guide you in the interpretation of the language rules when references are involved.

There are essentially two ways of implementing C++ references:

  1. As an annotation in the symbol-table of the compiler. This is only possible if the reference is only ever bound to one object, but it also stays closest to the concept of a reference. IMO, most compilers use this technique when possible, such as in the example presented here.
  2. As a pointer that gets automatically dereferenced on every operation. This is the fall-back solution, as it does not match the reference concept, but it does make it easier to implement reference-type function parameters without having to severely change the ABI.

In the presented example, there is never a way there can be a reference j that is not bound to the object i, so the compiler will most likely use the symbol-table annotation method of implementing the reference. This means that, after the declaration of both i and j, they can be used interchangeably in the code without any effect on the generated code or on the question if the behaviour is defined.

Register answered 6/10, 2010 at 8:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.