How is reference implemented in C++?

J

junw2000

For example,

int i = 5;
int &r = i;

Are i and r two different variables?
Or do i and r occupy the same memory space? that means they are the
same variable?

Thanks.
 
J

John Carson

For example,

int i = 5;
int &r = i;

Are i and r two different variables?
Or do i and r occupy the same memory space? that means they are the
same variable?

Thanks.

The C++ standard doesn't say how references are implemented. However, they
are often implemented in terms of const pointers. Thus

int & r = i;

may, "behind the scenes", be something like

int * const ptr = &i;

and a later

r = 9;

may be the equivalent of

*ptr = 9;
 
M

Mike Wahler

Re: How is reference implemented in C++?

THe language standard does not require any
particular mechanism. Each implementation
is free to do it in any way, as long as
the behavior is compliant.
For example,

int i = 5;
int &r = i;

Are i and r two different variables?

No. A reference is not an object, merely an
alternate name ('alias') for one.
Or do i and r occupy the same memory space?

NO. 'i' occupies storage. 'r' might or might not.
But it shouldn't matter.
that means they are the
same variable?

The names 'i' and 'r' refer to the same storage.
'r' isn't an object, but refers to one.

-Mike
 
B

bonjour2all

its like one variable with 2 names...
the same memory location is used...this is to the best of my knowledge
 
P

Peter_Julian

| For example,
|
| int i = 5;
| int &r = i;
|
| Are i and r two different variables?

Isn't i refering to an integer variable initialized to 5?
Thats exactly how references were "invented" in C++. The reference r is
just another name referring to the same integer variable that i is
referring to.

You are an instance of a Person class. You have both a name and a
nickname, i can use either to refer to the same person: you. Yet both
names are unique attributes of you. A nickname is an example of a
reference.

In my small, tiny brain, i need to store both your name and nickname
somewhere in different locations. Even though each refer to the same
object.

#include <iostream>
#include <ostream>

int main()
{
int i = 5;
int& r = i;

std::cout << "address of i = " << &i << std::endl;
std::cout << "address of r = " << &r << std::endl;

return 0;
}

/*
address of i = 006BFDF4
address of r = 006BFDF4
*/

| Or do i and r occupy the same memory space? that means they are the
| same variable?

They don't occupy the same memory space physically. The reference r and
i both *refer* to the same memory space occupied by that integer. Deep
down, a reference is nothing more than a pointer with special rules.
Ahem, lets make that: very special rules.

If you write a class that has one integer member and 2 integer member
references and you initialize the 2 references to refer to the original
integer in the class ctor, you'll end up with an instance of that class
composed of 3 entities, two of which "point" to the original integer.

Note the sizeof() output on this 32-bit platform.

#include <iostream>
#include <ostream>

class R
{
int n;
int& r;
int& rr;
public:
R(int x) : n(x), r(n), rr(n) { }
~R() { }
void display() const
{
std::cout << "&n = " << &n;
std::cout << "\n&r = " << &r;
std::cout << "\n&rr = " << &rr;
std::cout << "\nn = " << n;
std::cout << "\nr = " << r;
std::cout << "\nrr = " << rr;
std::cout << std::endl;
}
};

int main()
{
R var(99);
var.display();
std::cout << "sizeof(var) = " << sizeof(var);
std::cout << std::endl;

return 0;
}

/*
&n = 006BFDD8
&r = 006BFDD8
&rr = 006BFDD8
n = 99
r = 99
rr = 99
sizeof(var) = 12 // an integer(4 bytes) + 2 references(4 Bytes each)
*/

Its important for you to clear this issue because references provide a
special behaviour to the C++ language.

a) a reference is guarenteed to be valid. There is no such thing as an
unitialized reference.

b) a reference is unbreakable and therefore permanent. Reference r above
can't be modified to refer to another variable than i.

c) a reference can extend the lifetime of a variable.

As you can see, references were created specifically to eradicate
pointer hell. In fact, it does its job perfectly and transparently.
 
J

Jordan Abel

The C++ standard doesn't say how references are implemented. However, they
are often implemented in terms of const pointers. Thus

int & r = i;

may, "behind the scenes", be something like

int * const ptr = &i;

and a later

r = 9;

may be the equivalent of

*ptr = 9;

On the other hand, it could be more like

#define r i

and, at the end of the scope

#undef r
 
F

ferdinand.stefanus

Jordan said:
On the other hand, it could be more like

#define r i

and, at the end of the scope

#undef r

It won't work though if the scope where r is declared encloses a
sub-scope where another r is declared.
 
N

n2xssvv g02gfr12930

For example,

int i = 5;
int &r = i;

Are i and r two different variables?
Or do i and r occupy the same memory space? that means they are the
same variable?

Thanks.

The implementation may vary depending on scope and compiler
optimizations. Hence in some cases the reference provides
readable code but can be, and often is, optimized away in the
compiled code. But optimizing compilers do lots of things to
generate the type of code you require, hence for debugging the
resulting code as very direct correspondence to the original
source, whereas optimizing for speed or size almost definitely
doesn't.

JB
 
T

Tomás

posted:
For example,

int i = 5;
int &r = i;

Are i and r two different variables?
Or do i and r occupy the same memory space? that means they are the
same variable?

Thanks.


If some-one's name is John, and you say to them, "I'm going to call you
Brian from now on", then you'd do it like so:

int john = 6;

int &brian = john;

Just because you call him Brian, he's still John! There's no great use
for this inside a function, but it's handy for passing or returning
values from functions:

void SubtractFiveFromMe(int &k)
{
k -= 5;
}

int main()
{
int f = 7;

SubtractFiveFromMe( f );
}

We've passed "f" by reference, so our "Subtract" function actually alters
the variable in the function "main".

For returning values aswell:

int& GiveMeAVariable()
{
static int monkey = 7;

return monkey;
}

int main()
{
int &r = GiveMeAVariable(); //Now

r = 34;

//Or even simpler:

GiveMeAVariable() = 56;
}

-Tomás
 
J

junw2000

Thank you very much for your detail explanation.

But if
/*
&n = 006BFDD8
&r = 006BFDD8
&rr = 006BFDD8

Does it means that n, r and rr occupy the same memory space, since
their addresses are the same?

But sizeof(var) = 12 // an integer(4 bytes) + 2 references(4 Bytes
each).
It seems to me that they are three different integer variables. I am
confused.

Thanks.
 
J

Jordan Abel

It won't work though if the scope where r is declared encloses a
sub-scope where another r is declared.

That's why I said "like". [that is, the name becomes an alias, rather
than there being anything resembling a separate pointer]
 
G

Gavin Deane

Thank you very much for your detail explanation.

But if
/*
&n = 006BFDD8
&r = 006BFDD8
&rr = 006BFDD8

Does it means that n, r and rr occupy the same memory space, since
their addresses are the same?

Assuming something like

int n = 0;
int& r = n;
int& rr = r;

then n is an int variable. r and rr are both references to int. They
are just different ways to refer to the int they are initialised with.
In the code above, r refers to n, and so does rr.

You can not take the address of a reference. A reference is not an
object in its own right so talking about "the address or r" or "the
address of rr" in the above code does not make sense. When you apply
the address-of operator to a reference, you get the address of the
variable referred to.

So when you write &n, &r and &rr, you are not taking the addresses of
three different things. &n, &r and &rr are three different ways of
getting the address of n. Since you ask for the same thing three times,
it should come as no surprise that you get the same answer three times.
But sizeof(var) = 12 // an integer(4 bytes) + 2 references(4 Bytes
each).
It seems to me that they are three different integer variables. I am
confused.

What is var?

5.3.3/2
When [sizeof is] applied to a reference or a reference type, the result
is the size of the referenced type.

Gavin Deane
 
P

Peter_Julian

| Thank you very much for your detail explanation.
|
| But if
| /*
| &n = 006BFDD8
| &r = 006BFDD8
| &rr = 006BFDD8
|
| Does it means that n, r and rr occupy the same memory space, since
| their addresses are the same?

No, &r is not returning the address of the reference itself, its
returning the adress of the referred-to variable. You can't directly
measure the size of the reference itself either since sizeof(r) returns
the type size of the referred-to variable.

While the reference itself does occupy memory (usually the same size as
a pointer) its job is to serve the referred-to object. The 12 bytes on
this platform indirectly exposes the actual size. But the reference is
not allowed to return that value. If it did, it would break its purpose.

|
| But sizeof(var) = 12 // an integer(4 bytes) + 2 references(4 Bytes
| each).
| It seems to me that they are three different integer variables. I am
| confused.
|
| Thanks.
|

Its one integer and two pointers-on-steroids. You are confused because
on a typical 32 bit platform an integer happens to occupy the same space
in memory as a pointer. ok, try...

#include <iostream>
#include <ostream>

class N
{
double d;
double& r;
double& rr;
public:
N(double d_) : d(d_), r(d), rr(d) { }
~N() { }

/* friend op<< */
friend std::eek:stream& operator<<(std::eek:stream& os, const N& ref)
{
os << ref.d;
return os;
}
};

int main()
{
N n(11.1);

std::cout << " n = " << n; // op<<
std::cout << "\n sizeof(double) = " << sizeof(double);
std::cout << "\n sizeof(var) = " << sizeof(n);
std::cout << std::endl;

return 0;
}

/*
n = 11.1
sizeof(double) = 8
sizeof(var) = 16
*/
 
J

junw2000

Thanks a lot. I ran your code and got the same result.
I also print the sizeof(r), it is 8 bytes. sizeof(rr)=8 too.

Should sizeof(var)=sizeof(d)+sizeof(r)+sizeof(rr)?
If so, sizeof(var)=8+8+8=24.

But since the code outputs "sizeof(var) = 16",
so
sizeof(var)=sizeof(d)+sizeof(pointer)+sizeof(pointer)=8+4+4=16.

What is the problem here?

Thank you very much
 
P

Phlip

Thanks a lot. I ran your code and got the same result.
I also print the sizeof(r), it is 8 bytes. sizeof(rr)=8 too.

A reference is another name for its target. So sizeof(rr) is the same as
sizeof(int), the target item. That's because & will take the address of the
target int, etc. You can use the reference anywhere you can use its target.

The compiler is free to produce any opcodes it likes to support that
reference. A reference is not "a pointer with the indirection already
turned on". Naturally, many references secretly use pointer opcodes.
However, you would be surprised how many don't.
 

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
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top