On Mar 15, 4:41 am, igor.kul...@gma il.com wrote:
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_cas t)?
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.