Understanding references

I

igor.kulkin

References is a relatively basic feature of C++ language.

It might be a good thing to think of references as aliases to the
variables.
However it's good to think of references this way when you deal with
references which are local variables.
But references can also be function arguments (in fact they are more
useful this way) in which case it has to have the in-memory
representation.

Today it just hit me that references are much like pointers in a way
the it's a variable that stores a pointer to a piece of memory. It's
just that the syntax of using references is a little bit different
from using pointers (we don't need to dereference (dereference is a
little bit misleading here. I mean indirection operator "*".) it each
time we want to access the value to which it points).

(BTW please correct if something of what I am saying is wrong. I've
realized that I don't understand references in C although I though I
did.)

So then I asked myself what would return an address-of operator ('&')
applied to a reference. A common sense tells me that it should
basically return a pointer to the value which is referenced. So in
fact it would then have exactly the same value that a reference
variable itself (in terms of in memory storage).

Then I question myself:
1) Is it true that in-memory representation of pointers and references
are the same (i.e. they both contain address to the value the
reference/point)?
2) If the answer to #1 is yes, is it possible to convert from
reference to pointer and vice versa without using "&" and "*"
operators (e.g. with reinterpret_cast)?
3) Is it true at all that an address-of operator applied to a
reference would return a pointer to a referenced value rather than a
pointer to a reference itself (a reference variable is stored
somewhere in the memory so it has to have its own address)?
4) How can I get a pointer to the piece of memory which contains an
address stored in the reference (i.e. to the reference itself as a
contrast to a pointer to the value referenced by reference)?
 
K

Kai-Uwe Bux

References is a relatively basic feature of C++ language.

It might be a good thing to think of references as aliases to the
variables.
However it's good to think of references this way when you deal with
references which are local variables.
But references can also be function arguments (in fact they are more
useful this way) in which case it has to have the in-memory
representation.

Today it just hit me that references are much like pointers in a way
the it's a variable that stores a pointer to a piece of memory. It's
just that the syntax of using references is a little bit different
from using pointers (we don't need to dereference (dereference is a
little bit misleading here. I mean indirection operator "*".) it each
time we want to access the value to which it points).

(BTW please correct if something of what I am saying is wrong. I've
realized that I don't understand references in C although I though I
did.)

The question "what is a reference" is not answered by the standard. The
standard only specifies how references behave, not how they are
implemented. One can think of the term "reference" as being introduced
axiomatically by the standard.

So then I asked myself what would return an address-of operator ('&')
applied to a reference. A common sense tells me that it should
basically return a pointer to the value which is referenced.
Correct.


So in
fact it would then have exactly the same value that a reference
variable itself (in terms of in memory storage).

There is no such thing. Should a compiler use addresses to implement
references, the location of such an address would still not qualify as
a "variable" since there is no way of observing it from within the program,
i.e., you cannot get at the value of that imaginary variable.

Then I question myself:
1) Is it true that in-memory representation of pointers and references
are the same (i.e. they both contain address to the value the
reference/point)?

The standard does not require in-memory representations of references.

2) If the answer to #1 is yes, is it possible to convert from
reference to pointer and vice versa without using "&" and "*"
operators (e.g. with reinterpret_cast)?

It is possible, to go from a valid, non-zero pointer to an lvalue using *.
This lvalue can be used to initialize references.

It is possible to obtain a pointer to the object referenced by a reference
using &.

3) Is it true at all that an address-of operator applied to a
reference would return a pointer to a referenced value rather than a
pointer to a reference itself (a reference variable is stored
somewhere in the memory so it has to have its own address)?

There is no "reference variable" required by the standard. Should an
implementation use pointers internally to implement references, then there
still would be no standard way of obtaining the location of such pointers
in memory.

4) How can I get a pointer to the piece of memory which contains an
address stored in the reference (i.e. to the reference itself as a
contrast to a pointer to the value referenced by reference)?

You can't.


The situation is somewhat similar to vtables. The standard does not require
their existence and provides no method of getting at them. If an
implementation uses vtables to implement virtual functions, there still is
no method to access those things.

Also, it is purely psychological whether it helps you to think of references
in terms of a possible implementaion. I don't find it particularly helpful.
I also prefer not to think of virtual functions in terms of vtable entries.


Best

Kai-Uwe Bux
 
S

Stuart Redmann

References is a relatively basic feature of C++ language.

It might be a good thing to think of references as aliases to the
variables.
However it's good to think of references this way when you deal with
references which are local variables.
But references can also be function arguments (in fact they are more
useful this way) in which case it has to have the in-memory
representation.

Today it just hit me that references are much like pointers in a way
the it's a variable that stores a pointer to a piece of memory. It's
just that the syntax of using references is a little bit different
from using pointers (we don't need to dereference (dereference is a
little bit misleading here. I mean indirection operator "*".) it each
time we want to access the value to which it points).

(BTW please correct if something of what I am saying is wrong. I've
realized that I don't understand references in C although I though I
did.)

So then I asked myself what would return an address-of operator ('&')
applied to a reference. A common sense tells me that it should
basically return a pointer to the value which is referenced. So in
fact it would then have exactly the same value that a reference
variable itself (in terms of in memory storage).
Right.

Then I question myself:
1) Is it true that in-memory representation of pointers and references
are the same (i.e. they both contain address to the value the
reference/point)?

Informally spoken, yes. As this is an implementation detail, we don't
need to care what the compiler is doing to implement the semantics.

Note that we don't need an in-memory representation of a reference if
the referenced object lives in the same scope as the reference:

int func ()
{
int a;
int& b = a;
int*c = &a;
}

The compiler will certainly reserve only two 16/32/64-bit locations on
the stack, one for variable a and one for c. As b is only an alias for
a, the compiler will certainly only put b in the symbol table, so that a
and b are assigned the same memory location (as pointed out above, this
is an implementation detail, so this information is only relevant for
knowing what happens behind the scenes).
2) If the answer to #1 is yes, is it possible to convert from
reference to pointer and vice versa without using "&" and "*"
operators (e.g. with reinterpret_cast)?

Nope. As the compiler may not have to reserve memory for a reference
(see above), this operation cannot simply be treated as a casting.
3) Is it true at all that an address-of operator applied to a
reference would return a pointer to a referenced value rather than a
pointer to a reference itself (a reference variable is stored
somewhere in the memory so it has to have its own address)?
Yes.

4) How can I get a pointer to the piece of memory which contains an
address stored in the reference (i.e. to the reference itself as a
contrast to a pointer to the value referenced by reference)?

AFAIK, you can't (as it is not guaranteed that the reference really
needs space like a pointer does).

Regards,
Stuart
 
R

Roland Pibinger

Today it just hit me that references are much like pointers in a way
the it's a variable that stores a pointer to a piece of memory. It's
just that the syntax of using references is a little bit different
from using pointers (we don't need to dereference (dereference is a
little bit misleading here. I mean indirection operator "*".) it each
time we want to access the value to which it points).

In order to understand references it is important to remember that C++
was designed as a backward-compatible extension of C. If the C++
language were written from scratch it would not contain overlapping
elements like pointers and references. Being a superset (almost) of C
was a competitive advantage for C++ 15 - 20 years ago but later had
the opposite effect.

Best wishes,
Roland Pibinger
 
B

blangela

References is a relatively basic feature of C++ language.

It might be a good thing to think of references as aliases to the
variables.
However it's good to think of references this way when you deal with
references which are local variables.
But references can also be function arguments (in fact they are more
useful this way) in which case it has to have the in-memory
representation.

Today it just hit me that references are much like pointers in a way
the it's a variable that stores a pointer to a piece of memory. It's
just that the syntax of using references is a little bit different
from using pointers (we don't need to dereference (dereference is a
little bit misleading here. I mean indirection operator "*".) it each
time we want to access the value to which it points).

(BTW please correct if something of what I am saying is wrong. I've
realized that I don't understand references in C although I though I
did.)

So then I asked myself what would return an address-of operator ('&')
applied to a reference. A common sense tells me that it should
basically return a pointer to the value which is referenced. So in
fact it would then have exactly the same value that a reference
variable itself (in terms of in memory storage).

Then I question myself:
1) Is it true that in-memory representation of pointers and references
are the same (i.e. they both contain address to the value the
reference/point)?
2) If the answer to #1 is yes, is it possible to convert from
reference to pointer and vice versa without using "&" and "*"
operators (e.g. with reinterpret_cast)?
3) Is it true at all that an address-of operator applied to a
reference would return a pointer to a referenced value rather than a
pointer to a reference itself (a reference variable is stored
somewhere in the memory so it has to have its own address)?
4) How can I get a pointer to the piece of memory which contains an
address stored in the reference (i.e. to the reference itself as a
contrast to a pointer to the value referenced by reference)?

Below is some additional information I pass on to my C++ students
(hopefully it is correct :) ) in regards to references:

Let us start by looking at the following code:

const int & func ( int & ); // function prototype

int main()
{
int A =10;
int B = func(A);
B = 20; // this will not change A's value
return 0;
}

// This function receives int as a "pass by reference" and
// returns the same object as a "return by reference".

const int & func ( int & iref)
{
return iref;
}

Since A of main() is being passed by reference to func(), the address
of A and the address of iref of func() are identical (in other words,
iref references A). It would be a mistake to believe that because
func() is returning iref as a reference, that B also references A. B
will actually receive a copy of the value returned by func(), and
therefore modifying B will not modify A's value.

If we wanted B to reference A, we would need to change the function
call to:

int & B = func(A); // B is now being defined as a reference

Now B references A. But if we rebuild the solution with the change
above, we will get the following error (in MS VS 2003):

: error C2440: 'initializing' : cannot convert from 'const int' to
'int &'

This error occurs because we have specified that the function return
value is const and we are attempting to assign a reference to the
return value that is not const. We can fix this problem by declaring
the reference to be const:

const int & B = func(A); // B is now being defined as a const
reference

But if we make that change, and we rebuild our solution again, we will
now get the following error (in MS VS 2003):

: error C2166: l-value specifies const object

What line of code is the compiler complaining about now? The following
line of code:

B = 20; //attempting to change B's value, which would change A's value
as well!

Now that the reference is const, we are of course not allowed to
change its value. If we were allowed to change B's value, realize
that we would be changing A's as well (since B is a reference to A).

Please note that it is common, as in the example above, when returning
a reference, to declare the returning reference to be const, to
protect the object being returned from being changed.

On to a different, but related, topic. Let us modify func() in the
following way:

const int & func ( int & iref)
{
int X;
...
return X;
}

Is the above change ok?

The answer is no. Why? Because we are attempting to return a reference
to X. But X is an automatic variable and will no longer exist by the
time the reference to X is returned to main(). This is because the
stack frame on which X is stored will have been popped off the
function call stack (read section 6.11 of Deitel & Deitel's "C++ How
To Program" 5th edition for details on how this works).

Will the compiler generate an error?

No. And if the returned value is immediately copied to another
variable in main(), upon returning to main(), the programmer may be
"lucky" and the memory location on the stack where X was stored may
not yet have been overwritten by some other value. In such a case, the
program may appear to work correctly. But this is not a guaranteed
result, and the programmer's "luck" is likely to change at some time
in the future!

If we make the following change, is it ok now?

const int & func ( int & iref)
{
static int X; // X is now static
...
return X;
}

Yes, now we are fine. A static variable, just like a global variable,
is permanent (global variable is created before main() starts
execution, while a static variable is created when the block of code,
in which it is declared, executes for the first time). Therefore it is
now safe to return a reference to X. But realize that we should make
a copy of the returned reference before invoking func() again, since
X's value may be modified when func() is invoked again (thus changing
any variable that references X).

I may have mentioned in class that dynamically created objects
(objects created with the "new" operator) are stored on the "heap" and
that automatic variables (variables of block scope for example) are
stored on the "call stack". Where are static variables (like the last
version of X above) and global variables stored in memory? The answer
is usually in the same general area of memory where your executable
code is stored. Though, some C++ compilers will store static and
global variables on the heap as well.
 
B

Bluejack

Today it just hit me that references are much like pointers in a way
the it's a variable that stores a pointer to a piece of memory. It's
just that the syntax of using references is a little bit different
from using pointers (we don't need to dereference (dereference is a
little bit misleading here. I mean indirection operator "*".) it each
time we want to access the value to which it points).

The two important differences between references and pointers are:

1) References can never be null; they can never reference arbitrary
and invalid memory locations. (Well... it might be possible to do
something nasty by creating a reference and then deleting the
original...)

2) Unlike pointers, references are not variables distinct from what is
referenced, and thus cannot be accessed in any way other than the
referenced object.

Your original statement:
It might be a good thing to think of references as aliases to the
variables.

It the better statement. When passed through to functions, I find it
is a better mental exercise to think of reference as an exception to
the scoping paradigm than to think of them as pointers. IE., the scope
of the referenced object has been extended to include this method.

But the best way to think of them is on their own terms. This is a
reference; these are the rules for references; this is how to use
references. No analogies, no mental gymnastics. References are simply
references.
 
B

blangela

The two important differences between references and pointers are:

1) References can never be null; they can never reference arbitrary
and invalid memory locations. (Well... it might be possible to do
something nasty by creating a reference and then deleting the
original...)

2) Unlike pointers, references are not variables distinct from what is
referenced, and thus cannot be accessed in any way other than the
referenced object.

Your original statement:


It the better statement. When passed through to functions, I find it
is a better mental exercise to think of reference as an exception to
the scoping paradigm than to think of them as pointers. IE., the scope
of the referenced object has been extended to include this method.

But the best way to think of them is on their own terms. This is a
reference; these are the rules for references; this is how to use
references. No analogies, no mental gymnastics. References are simply
references.

Let me add 3) to the list above:

3) In C++, whatever object a reference is initialized to be reference
to, that is the object it will reference for the life of the reference
(I beleive this may not be case in all programming languages that
support references). Pointers on the other hand, can be made to point
to several different ojects during the lifetime of the pointer (unless
the pointer is const).
 
B

blangela

Let me add 3) to the list above:

3) In C++, whatever object a reference is initialized to be reference
to, that is the object it will reference for the life of the reference
(I beleive this may not be case in all programming languages that
support references). Pointers on the other hand, can be made to point
to several different ojects during the lifetime of the pointer (unless
the pointer is const).- Hide quoted text -

- Show quoted text -

I might have added: "Which is why a reference _MUST_ be initialized at
the point it is defined, just as with a const pointer."
 
D

Dave Rahardja

In order to understand references it is important to remember that C++
was designed as a backward-compatible extension of C. If the C++
language were written from scratch it would not contain overlapping
elements like pointers and references. Being a superset (almost) of C
was a competitive advantage for C++ 15 - 20 years ago but later had
the opposite effect.

I doubt C had anything to do with it. References and pointers serve different
purposes. Languages that lack a distinction between references and pointers
(like Java) live in denial--they just call both constructs the same thing, and
deal with the problems of both paradigms all the time. They also make it
difficult to deal with the low-level operations needed for high performance
code, which are the forte of pointers.

-dr
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top