Request for clarification: references

1 view
Skip to first unread message

John the newbie

unread,
Jun 10, 2002, 6:47:36 PM6/10/02
to
Hi everybody,

while I'm quite familiar with the meanings of C++ constructs that
involve references, I do not have a clear definition of what a
reference actually _is_.
Wandering through the standard I was not able to find my answer.

In particular, which of the following holds?

1. references are l-values (they refer to objects)

2. references aren't objects by themselves

3. reference are variables

4. references are names.

5. references are variable names.

6. references are entities (clause 3, par. 3)

Moreover, if 4 (or 5) is true then they name the object they refer to.
Therefore, why I can say that

class Dummy {};

Dummy d;
Dummy& r = d;

d is an object while r not? (I should say that d is the "name" of an
object, right?)

6. if references are not objects, what does "lifetime of references"
mean?

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

Michiel Salters

unread,
Jun 11, 2002, 11:03:42 AM6/11/02
to
what...@yahoo.com (John the newbie) wrote in message news:<102a8848.02061...@posting.google.com>...

> Hi everybody,
>
> while I'm quite familiar with the meanings of C++ constructs that
> involve references, I do not have a clear definition of what a
> reference actually _is_.
> Wandering through the standard I was not able to find my answer.
>
> In particular, which of the following holds?
>
> 1. references are l-values (they refer to objects)

expressions can be lvalues, an expression of the form
(t) is an lvalue if t is a reference.

> 2. references aren't objects by themselves

Correct. Objects use memory, and taking their address gives
the memory used.

> 3. reference are variables

"[dcl.init.ref] 8.5.3 References
1 A variable declared to be a T&, ... "

> 4. references are names.

"sometimes have", not "are":

int& foo() {
static int i=0;
return i;
}
The returned reference doesn't have a name.



> 5. references are variable names.

Same problem.

Regards,
--
Michiel Salters

t...@cs.ucr.edu

unread,
Jun 12, 2002, 2:24:26 PM6/12/02
to
John the newbie <what...@yahoo.com> wrote:
[...]
: I do not have a clear definition of what a reference actually _is_.

That's because the Standard isn't clear on what a reference is and
why. But you're asking the right questions. To cut through the fog
it helps to keep in mind the function int& f(){ return *new int; }.

: Wandering through the standard I was not able to find my answer.

: In particular, which of the following holds?

: 1. references are l-values (they refer to objects)

Strictly speaking, an l-value is a particular kind of expression,
i.e., a string of symbols. So, the source-code string "f()" is an
lvalue, but the entity that f returns is not.

: 2. references aren't objects by themselves

That's what they keep trying to tell me. The reason given is that
"references don't have addresses" (whatever that means). Obviously,
you can't take the address of a reference because it refers all
operations to its referent. In fact, most of the arguments about why
references shouldn't be considered objects apply equally well to
variables whose value is never modified and whose addresses are never
taken.

: 3. reference are variables

Well, variables are named objects. So, if you agree that references
aren't objects, then they can't be variables.

: 4. references are names.

That's another thing they try to tell me. Also, sometimes they say
that a "reference is an alias" (whatever that means). On page 21, the
standard defines a name to be "a use of an identifier ...". But, if
we go back to the function f() above, we see that "f()" is an
expression and that the entity returned by f doesn't have a name. Of
course, we could use it to initialize a named reference.
Alternatively, we could use it to access the newly allocated int
object, as in "f()=3".

: 5. references are variable names.

Not so for the reference returned by f().

: 6. references are entities (clause 3, par. 3)

If we accept that references are not objects, then, by process of
elimination, clause 3, par. 3 says that references are non-entities.

: Moreover, if 4 (or 5) is true then they name the object they refer to.

Not the reference returned by f(). Remember "a name is a use of
an identifier ...".

: Therefore, why I can say that

: class Dummy {};

: Dummy d;
: Dummy& r = d;

: d is an object while r not? (I should say that d is the "name" of an
: object, right?)

In the above, d is an object and "d" is its name. Similarly, r is a
reference and "r" is its name.

: 6. if references are not objects, what does "lifetime of references"
: mean?

Bingo! You win the prize for that one.


So, how should one really view references? Unless you are a language
lawyer, my advice is to close your eyes to the nonsense in the
Standard regarding references:

The obvious implementation of a reference is as a (constant) pointer
that is dereferenced each time it is used. It doesn't do much harm
thinking about references that way, as long as one remebers that a
references isn't an object that can be manipulated the way a pointer
is ... [The C++ Programming Lanuage, Special Edition, p. 98]

Stroustrup goes on to say:

In some cases, the compiler can optimize away a references so
that there is no object representing that reference at run-time.

But, of course, the same is true of most const objects. (You can't
optimize away const fields of POD structs.)

So, what pitfalls are there in viewing references as auto-dereferenced
pointers?

- The Standard defines the sizeof(T&) to be sizeof(T) rather than
sizeof(T*). (I consider that choice to be both unfortunate and
unhelpful, but it's official.)

- Any struct or class object that contains a reference is non-POD,
which means that it isn't subject to C's layout rules.

- Const references can be initialized to refer to an rvalues,
while the corresponding initialization for a pointer doesn't
work.

- There are a bunch of (seemingly arbitrary) prohibitions on
refereces: no arrays of references, no references to references,
etc.

There are few more, some of which are extremely obscure.

Tom Payne

Gennaro Prota

unread,
Jun 13, 2002, 12:30:20 PM6/13/02
to
On Wed, 12 Jun 2002 18:24:26 GMT, t...@cs.ucr.edu wrote:

>John the newbie <what...@yahoo.com> wrote:
>[...]
>: I do not have a clear definition of what a reference actually _is_.
>
>That's because the Standard isn't clear on what a reference is and
>why. But you're asking the right questions. To cut through the fog
>it helps to keep in mind the function int& f(){ return *new int; }.
>
>: Wandering through the standard I was not able to find my answer.
>

All this is absolutely embarrassing. I came exactly upon the same path
of questions while preparing a defect report concerning the wording in
5.3.3 [expr.sizeof] and I have deferred the submission for this very
reason.


Trying, like you, to cut through the fog:


References may have names (8.3.2) and, when they have, the name
*denotes* the reference (whatever it is), not the referenced entity
(see 3.5p2)

The intent seems to be that they are not objects, because there are a
lot of places where the standard uses the wording "object or
reference" (grep to believe).

They have a type, though. But they are not expressions because they
are not names. Hmmm.... my first idea was to distinguish between
"referring" to something and "denoting it": note that an expression
(when it is an l-value) *refers* to an object (and not *denotes* an
object). So, I thought, the idea could be that given the declarations:

int i = 3;
int & r = i;

the name r refers to an object (also denoted by i) but *denotes* a
reference. A reference, in itself, refers to an object (at first some
wordings, like that in 8.3.6p10, seemed to contradict me but they
could have been oversights and I was trying to grasp the essentials,
without clinging to the words)

But if you go reading clause 3 [basic], then all this castle collapses
under your eyes. Moreover, and this is probably the most serious
issue, see 3.7p4: "The lifetime of a reference is its *storage
duration*" Aaaarghhhh!!!!

What to do now? Well, let me explicitly mention a name so that someone
feels called in: Steve Clamage, please, tell us what a reference is!
;)))

Genny.

t...@cs.ucr.edu

unread,
Jun 14, 2002, 3:45:53 AM6/14/02
to
Gennaro Prota <gennar...@yahoo.com> wrote:

: On Wed, 12 Jun 2002 18:24:26 GMT, t...@cs.ucr.edu wrote:

:>John the newbie <what...@yahoo.com> wrote:
:>[...]
:>: I do not have a clear definition of what a reference actually _is_.
:>
:>That's because the Standard isn't clear on what a reference is and
:>why. But you're asking the right questions. To cut through the fog
:>it helps to keep in mind the function int& f(){ return *new int; }.
:>
:>: Wandering through the standard I was not able to find my answer.
:>

: All this is absolutely embarrassing.

As well it should be!

You need to know that some of us have made a bit of a ritual out of
arguing this point. By now, it reminds me of prisoners who gave every
joke a number -- to tell a joke simply yelled out its number.

: I came exactly upon the same path


: of questions while preparing a defect report concerning the wording in
: 5.3.3 [expr.sizeof] and I have deferred the submission for this very
: reason.

Okay. It'ss unhelpful to define sizeof(T&) to be sizeof(T). We
already know that from sizeof(T). What we want to find out from
sizeof(T&) is how much space is taken up by a reference-to-T. Yes, I
know that entities of type T& are implicitly const and their bindings
can often be detertermined at compile time so they don't need to be
stored at run time. What's new? The same holds for const int's.

Nevertheless, T&'s and const int's are often not initialized until run
time, in which case some representation needs to be stored somewhere.

: Trying, like you, to cut through the fog:

: References may have names (8.3.2) and, when they have, the name
: *denotes* the reference (whatever it is), not the referenced entity
: (see 3.5p2)

Which is as it should be.

: The intent seems to be that they are not objects, because there are a


: lot of places where the standard uses the wording "object or
: reference" (grep to believe).

It's amazing the contortions that the Standard goes through to
maintain that "references aren't objects". By the way, I believe that
the Standard manages to pull it off without explicit contradiction.
But the price in human confusion is awesome.

: They have a type, though. But they are not expressions because they
: are not names.

Oops! An expression is a string of characters. A name is an
expression, but a reference is not. In the example I gave "f()"
is a three-character expression that denotes a nameless reference.

: Hmmm.... my first idea was to distinguish between


: "referring" to something and "denoting it":

Good idea. You're on the right track.

: note that an expression
: (when it is an l-value) *refers* to an object (and not *denotes* an
: object).

Arrggghhh! In C89, lvalues "designate". Maybe distinguishing between
"denoting" and "referring" isn't all that helpful.

So let's distinguish between syntactic entities and semantic entities.
There should be some sort of mapping between syntactic entities, which
are strings of symbols, and the semantic things they represent
(denote, designate, refer to), which as everyone knows are elments of
continuous lattices. ;-) References are semantic entities, which are
somehow akin to object-valued objects. In a sane world the
object-to-value mapping would map them to their referrents.

: So, I thought, the idea could be that given the declarations:

: int i = 3;
: int & r = i;

: the name r refers to an object (also denoted by i) but *denotes* a
: reference.

I would say that the identifier "r" denotes a reference that refers to
the same object that the identifier "i" denotes. Are we on the same
page?

: A reference, in itself, refers to an object (at first some


: wordings, like that in 8.3.6p10, seemed to contradict me but they
: could have been oversights and I was trying to grasp the essentials,
: without clinging to the words)

IMHO, you've identified a defect: expressions *denote* and reference
*refer*. The Standard has it backwards.

: But if you go reading clause 3 [basic], then all this castle collapses


: under your eyes. Moreover, and this is probably the most serious
: issue, see 3.7p4: "The lifetime of a reference is its *storage
: duration*" Aaaarghhhh!!!!

What's with non-entities having storage duration? And, what's a
dangling name? And, how do you store the bindings of references
members of an arbitrarily large list of structs, if not in objects?

Why not simply take the view that references are objects and make the
Standard a lot simpler? Even Stroustrup says that thinking about
references that way "doesn't do much harm."

: What to do now? Well, let me explicitly mention a name so that someone


: feels called in: Steve Clamage, please, tell us what a reference is!
: ;)))

It makes no difference what Steve (or you or I) say that references
are. Humpty Dumpty called it: "The term 'reference' means whatever
the Standard says it means, neither more nor less." (But we don't
have to like it.)

Tom Payne

Gennaro Prota

unread,
Jun 15, 2002, 2:20:30 AM6/15/02
to
On Fri, 14 Jun 2002 01:45:53 CST, t...@cs.ucr.edu wrote:

>Gennaro Prota <gennar...@yahoo.com> wrote:
>: On Wed, 12 Jun 2002 18:24:26 GMT, t...@cs.ucr.edu wrote:
>
>:>John the newbie <what...@yahoo.com> wrote:
>:>[...]
>:>: I do not have a clear definition of what a reference actually _is_.
>:>
>:>That's because the Standard isn't clear on what a reference is and
>:>why. But you're asking the right questions. To cut through the fog
>:>it helps to keep in mind the function int& f(){ return *new int; }.
>:>
>:>: Wandering through the standard I was not able to find my answer.
>:>
>
>: All this is absolutely embarrassing.
>
>As well it should be!
>
>You need to know that some of us have made a bit of a ritual out of
>arguing this point. By now, it reminds me of prisoners who gave every
>joke a number -- to tell a joke simply yelled out its number.

Oh oh... too idiomatic for my English! Do you mean that this issue is
extremely well-known? (As a prisoner I would have liked to be
informed, in that case! ;)) And that you raised it so many times that
it has almost become a crusade convincing others that there's a
problem in the standard?


>: I came exactly upon the same path
>: of questions while preparing a defect report concerning the wording in
>: 5.3.3 [expr.sizeof] and I have deferred the submission for this very
>: reason.
>
>Okay. It'ss unhelpful to define sizeof(T&) to be sizeof(T). We
>already know that from sizeof(T). What we want to find out from
>sizeof(T&) is how much space is taken up by a reference-to-T. Yes, I
>know that entities of type T& are implicitly const and their bindings
>can often be detertermined at compile time so they don't need to be
>stored at run time. What's new? The same holds for const int's.


Who said that my DR concerned this? :) Seriously, it concerns the fact
that 5.3.3 talks about the object representation of the sizeof
operand. The issue is that the operand itself is either an expression
or a parenthesized type-id, both things that don't have an "object
representation". Of course, unlike other operators, the intent is that
the operand of sizeof is a syntactic entity (something that lives in
the compile-time world only). When preparing a rewording, the only
problem I came upon was that, without knowing if a reference is an
entity, an expression or something else, I was not able to determine
if the sentence "When applied to a reference" in 5.3.3p2 was correct.

The fact that sizeof(T&) is the same of sizeof(T) is another story and
frankly doesn't disturb me.

>
>Nevertheless, T&'s and const int's are often not initialized until run
>time, in which case some representation needs to be stored somewhere.
>
>: Trying, like you, to cut through the fog:
>
>: References may have names (8.3.2) and, when they have, the name
>: *denotes* the reference (whatever it is), not the referenced entity
>: (see 3.5p2)
>
>Which is as it should be.
>
>: The intent seems to be that they are not objects, because there are a
>: lot of places where the standard uses the wording "object or
>: reference" (grep to believe).
>
>It's amazing the contortions that the Standard goes through to
>maintain that "references aren't objects". By the way, I believe that
>the Standard manages to pull it off without explicit contradiction.

Tell me how. I said you where I see some contradictions. Now you
should say me why they aren't.

>But the price in human confusion is awesome.
>
>: They have a type, though. But they are not expressions because they
>: are not names.
>
>Oops! An expression is a string of characters. A name is an
>expression, but a reference is not. In the example I gave "f()"
>is a three-character expression that denotes a nameless reference.

I'm not saying that names are the only possible expressions. BTW, in
standard terminology names are not expressions: identifiers
(id-expressions) are, while a name is *a use* of an identifier. In any
case, identifiers are not the only expressions, of course, but I can't
see what kind of expression a reference could be if not an identifier.


As to f(), it is per se a function-call expression. When I think about

f() = 3;

my mind fluctuates a bit, like when you observe some M. Escher's
works. On one hand I'd like to think that f() denotes the function
call, not what the function returns. On the other hand there's the
fact that you can put the expression on the left side of an assignment
operator. At this point, reading 5.17 it seems to me that, though
there's not that neat terminological distinction between "denoting"
and "referring to" that I would like, it still makes sense to think
that f() denotes a reference and that the reference, in its turn,
refers to (or denotes, as 5.17p6 says) the int object.

In this regard, 5.17p6 is IMHO a part of the definition of reference
semantics.

Like you, I'm not able to see references as syntactical entities. But
I may be wrong.

[distinction between syntactic and semantic entities snipped... I
agree on it]


>: So, I thought, the idea could be that given the declarations:
>
>: int i = 3;
>: int & r = i;
>
>: the name r refers to an object (also denoted by i) but *denotes* a
>: reference.
>
>I would say that the identifier "r" denotes a reference that refers to
>the same object that the identifier "i" denotes. Are we on the same
>page?

Exactly.

>: A reference, in itself, refers to an object (at first some
>: wordings, like that in 8.3.6p10, seemed to contradict me but they
>: could have been oversights and I was trying to grasp the essentials,
>: without clinging to the words)
>
>IMHO, you've identified a defect: expressions *denote* and reference
>*refer*. The Standard has it backwards.
>
>: But if you go reading clause 3 [basic], then all this castle collapses
>: under your eyes. Moreover, and this is probably the most serious
>: issue, see 3.7p4: "The lifetime of a reference is its *storage
>: duration*" Aaaarghhhh!!!!
>
>What's with non-entities having storage duration?

A non-object having a storage duration?

>And, what's a
>dangling name? And, how do you store the bindings of references
>members of an arbitrarily large list of structs, if not in objects?
>
>Why not simply take the view that references are objects and make the
>Standard a lot simpler? Even Stroustrup says that thinking about
>references that way "doesn't do much harm."
>
>: What to do now? Well, let me explicitly mention a name so that someone
>: feels called in: Steve Clamage, please, tell us what a reference is!
>: ;)))
>
>It makes no difference what Steve (or you or I) say that references
>are. Humpty Dumpty called it: "The term 'reference' means whatever
>the Standard says it means, neither more nor less." (But we don't
>have to like it.)

I don't see what the standard says it means. Do you? At least I would
like to hear from someone involved in the standardization what was the
intent.


Genny.

t...@cs.ucr.edu

unread,
Jun 15, 2002, 12:28:41 PM6/15/02
to
Gennaro Prota <gennar...@yahoo.com> wrote:
[...]
: Oh oh... too idiomatic for my English! Do you mean that this issue is
: extremely well-known?

It has been argued into the ground on numerous occasions.

: (As a prisoner I would have liked to be informed, in that case! ;))

So, google back to some long and tedious threads involving James
Kanze, occasionally Steve Clamage, and many others (including me). I
found them very informative. By now, everyone's arguments and
positions are familiar to everyone else. More importantly, by now
everyone is familiar with and understands their own perspective
better. For example, if someone says that a reference is a name, it's
very predictable that I will drag out my favorite counter-example:


int& f() { return *new int; }

: And that you raised it so many times that


: it has almost become a crusade convincing others that there's a
: problem in the standard?

Problem? What problem? They've convinced me. ;-)

[...]
: it concerns the fact


: that 5.3.3 talks about the object representation of the sizeof
: operand. The issue is that the operand itself is either an expression
: or a parenthesized type-id, both things that don't have an "object
: representation". Of course, unlike other operators, the intent is that
: the operand of sizeof is a syntactic entity (something that lives in
: the compile-time world only). When preparing a rewording, the only
: problem I came upon was that, without knowing if a reference is an
: entity, an expression or something else, I was not able to determine
: if the sentence "When applied to a reference" in 5.3.3p2 was correct.

The operand has to be evaluated before sizeof can be applied to it.
If the operand expression denotes a reference, then an implicit
reference-to-referent conversion takes place, and sizeof gets applied
to the referent.

: The fact that sizeof(T&) is the same of sizeof(T) is another story and


: frankly doesn't disturb me.

Hmmmm. I thought you were on my side. ;-)

[...]
:>It's amazing the contortions that the Standard goes through to


:>maintain that "references aren't objects". By the way, I believe that
:>the Standard manages to pull it off without explicit contradiction.

: Tell me how. I said you where I see some contradictions. Now you
: should say me why they aren't.

A well-known result in logic states that if a set of axioms (aka
specifications) has a model (aka implementation) then they are not
inconsistent. I believe that Stroustrup implemented references well
before the Committee wrote the specifications.

[...]
: BTW, in standard terminology names are not expressions: identifiers


: (id-expressions) are, while a name is *a use* of an identifier.

AFAIK, a *use* of an identifier is any occurrence of that identifier
other than those where it is the subject of a declaration.

: In any


: case, identifiers are not the only expressions, of course, but I can't
: see what kind of expression a reference could be if not an identifier.

Again, expressions are syntactic entities, while references are
semantic. They live in two different worlds. (In my own view of the
world, a reference is simply an object-valued object, just like an int
variable is an integer-valued object.)

: As to f(), it is per se a function-call expression. When I think about

: f() = 3;

: my mind fluctuates a bit, like when you observe some M. Escher's
: works. On one hand I'd like to think that f() denotes the function
: call, not what the function returns.

Think in terms of bottom-up evaluation of the syntax tree, and note
that there are some implicit operations in that tree, e.g.,
lvalue-to-rvalue conversion, which is officially discussed in the
standard, and reference-to-referent conversion, which may not be
officially discussed but seems to make references a bit more
comprehensible. So, the expression "f()" when evaluated yields a
reference to a newly created int object. That reference undergoes
implicit reference-to-referent conversion, which yields that newly
created int object. Therefore, "f()" is an lvalue, since it denotes
(i.e., its evaluation yields) an object. (Actually, some rvalues
denote objects as well, but let's not go there.)

: On the other hand there's the


: fact that you can put the expression on the left side of an assignment
: operator.

... provided that it is an lvalue.

: At this point, reading 5.17 it seems to me that, though


: there's not that neat terminological distinction between "denoting"
: and "referring to" that I would like, it still makes sense to think
: that f() denotes a reference and that the reference, in its turn,
: refers to (or denotes, as 5.17p6 says) the int object.

That works for me.

: In this regard, 5.17p6 is IMHO a part of the definition of reference
: semantics.

Perhaps, the better way to look at it is the following. Any
occurrence of an expression whose evaluation terminates in an implicit
conversion has two denotations, a pre-conversion denotation and a
post-conversion denotation. Under that view, in "i=j" the
pre-conversion denotation of "j" is an int object, while the
post-conversion denotation of "j" is the integer value of that object.
Similarly, under that view, f() denotes both the returned reference
and its referent.

[...]
:>It makes no difference what Steve (or you or I) say that references


:>are. Humpty Dumpty called it: "The term 'reference' means whatever
:>the Standard says it means, neither more nor less." (But we don't
:>have to like it.)

: I don't see what the standard says it means. Do you? At least I would
: like to hear from someone involved in the standardization what was the
: intent.

The Standard tells how references should behave in each and every
situation. That is sufficient for implementing the language, and it
should be sufficient for a retentive programmer everyday programmers.
Unfortunately, the Standard fails to provide a coherent view of what
references are that they should have this particular set of
properties, but perhaps that is the responsibility of textbook writers
rathar than standards writers.

Tom Payne

Reply all
Reply to author
Forward
0 new messages