How to Find the Address of a Reference

Is there any way to find the address of a reference?

References don't have their own addresses. Although references may be implemented as pointers, there is no need or guarantee of this.

The C++ FAQ says it best:

Unlike a pointer, once a reference is
bound to an object, it can not be
"reseated" to another object. The
reference itself isn't an object (it
has no identity; taking the address of
a reference gives you the address of
the referent; remember: the reference
is its referent).

Please also see my answer here for a comprehensive list of how references differ from pointers.

The reference is its referent

Is always the address of a reference equal to the address of origin?

Unfortunately, many people confuse logical and physical meaning of C++ references.

Logical level

There is a crucial thing I found for myself about C++ references:
As soon as I have initialized a reference, it becomes unpronounceable. And what I mean by "unpronounceable" is the fact that always when you name a reference in runtime executable code - you automatically get the variable it refers to, so there is no way you can touch the reference itself. Reference is just an alternative name (an alias) for a variable.

So if you have something like int i_var = 10; int& i_ref = i; no matter what executable expression you form with it, any mentioning of i_ref would actually mean i_var.

Also, some people find helpful to think of a reference as a "self-dereferencing pointer". So imagine you have a pointer int* p, but each and every time you refer to it as p you actually mean *p. For instance, p = 10 would mean *p = 10 and &p would mean &(*p) - the address of int which p is pointing too. That is how logically references work.

It applies to your code too. As soon as you have
Point &p = plist[2]; (occured when you called func(plist[2])) then p and plist[2] start reference to the same thing - some Point object stored by the index of 2 in plist. So now &plist[2] and &p are absolutely equal.

Type system level

If you noticed, I used terms "runtime executable code" or "executable expression". Let me clarify.

The compiler actually knows the difference between a and b:

int a = 0;
int& b = a;

std::cout << std::boolalpha
<< std::is_same_v<decltype(a), decltype(b)>; // -> false

As you see a and b types are different. However, std::is_same_v<decltype(a), decltype(b)> gets evaluated at compile time so i did not consider it as an "executable expression".

Physical level

Notice, that until now I did not said that the address of a reference and the address of variable being referenced are the same. Why? Because if you think logically - they are not.

References have to be implemented in some way, whether you like it or not. I believe, in the example with i_var and i_ref compiler will simply replace all i_ref with i_var and any physical representation of "reference" will never exist. On the other hand, if you store reference inside a class it is likely to be implemented with a pointer.
Although, an implementation is compiler dependent, if reference actually is a pointer under the hood, it is obvious that the address of this pointer and the address of the object it is pointing to are different.

However, why should you care? You will never know the address of reference! In any executable expression, when you say i_ref you imply i_var, remember?:)


OK, if you are really-really curious "what is the address of a reference", there is a one case when you can figure it out - when reference is a member of a class:

int main()
{
int var = 10;
int& real_ref = var;
struct { int& ref; } fake_ref = { var };

std::cout << &var << std::endl; // address of var
std::cout << &real_ref << std::endl; // still address of var
std::cout << &fake_ref << std::endl; // address of reference to var

std::cout << sizeof var << std::endl; // size of var
std::cout << sizeof real_ref << std::endl; // still size of var
std::cout << sizeof fake_ref << std::endl; // size of reference to var

return 0;
}

Output on x64 compiler:

000000A9272FFBA4   <- same
000000A9272FFBA4 <- same
000000A9272FFBC0 <- different
4 <- same
4 <- same
8 <- different (8 on 64 bit and 4 on 32 bit compiler)

Is there any way to find the address of a reference?

References don't have their own addresses. Although references may be implemented as pointers, there is no need or guarantee of this.

The C++ FAQ says it best:

Unlike a pointer, once a reference is
bound to an object, it can not be
"reseated" to another object. The
reference itself isn't an object (it
has no identity; taking the address of
a reference gives you the address of
the referent; remember: the reference
is its referent).

Please also see my answer here for a comprehensive list of how references differ from pointers.

The reference is its referent

How to get a pointer from a reference?

Yes, applying the address-of operator to the reference is the same as taking the address of the original object.

#include <iostream>

struct foo {};

void bar( const foo& obj )
{
std::cout << &obj << std::endl;
}

int main()
{
foo obj;
std::cout << &obj << std::endl;
bar( obj );

return 0;
}

Result:

0x22ff1f
0x22ff1f

Taking the address of a c++ reference for passing to a pointer

You can't actually do anything with a reference variable except initialize it on definition. Every use of the reference variable after initialization is a direct access to the original variable, what it references.

In your case, when you do &v in the function function, you don't get the address of the local reference variable v, but the address of the variable v from the main function.

In short, this is fine.

A reference variable's address and value C++

I know that a reference variables's address cannot be changed once
set,

References have nothing to do with addresses. Don't think of references as special pointers.

Unless you are talking about how a compiler might implement references. But this is a completely different level of abstraction. On a C++ programmer level, you are not looking at the language from the same point of view as a compiler writer; there is no such thing as a "reference variable's address". Objects have addresses, and a reference is just a different way to name an object.

Or, as I like to explain it to beginners, a reference is the object.

but when I run the command how is my reference's value change but
the address is the same?

In the following line:

int &ref = a;   //&ref is 0x28fee

You are declaring ref to be a reference to a. Using the explanation from above, ref is a. So when you then go on and write &ref afterwards (using the & character to invoke the address-of operator, rather than declaring a reference), what happens is equivalent to what happens when writing &a. It is therefore not surprising that the result is identical. It's one and the same object, so the address must be the same.

ref = b;        //value of ref = 5, address is still 0x28fee

This is the same as writing a = b;. It assigns the value of b to a, because ref is just another way to say a. No addresses are changed when values are assigned to ints.

Lastly, is it correct to assume that the "&" sign is same the one we
use in pointers?

No, not at all. Reiterating my point from above: & has different meanings in C++. You use it to declare references or to take addresses of objects. Actually, there are even more meanings, considering that & is also the bit-wise AND operator, as in a & b. Pairs of &, i.e. &&, extend the list of possible meanings to include the logical AND operator and C++11 rvalue references.


From a teaching point of view, it is of course unfortunate that & is overloaded for reference declarations and the address-of operator. As far as I know, & was chosen for references because back then, it was difficult to add new keywords (like ref) to C++ as backward compatibility with C was a huge concern at that time, and adding ref as a keyword would have meant that C code like int ref = 0; would no longer compile.

C++ had to introduce at least some new keywords (e.g. throw), but in certain cases it was technically possible and/or politically necessary to do without them.



Related Topics



Leave a reply



Submit