Why pointer to a refernce is not allowed in C++?????

Recommended Answers

All 16 Replies

because you cannot take address of reference.

commented: Good Comment +3

who said you can't make a pointer to a reference?

void foo(int& x)
{
    int* p = &x;
    *p = 0;
}

If that is not what you mean then please post an example.

who said you can't make a pointer to a reference?

void foo(int& x)
{
    int* p = &x;
    *p = 0;
}

If that is not what you mean then please post an example.

AD, It's pointer to int which points to the integer which was refered-to by the reference.

references in c++ are (almost) identical to pointers. a pointer to a reference is really nothing more than a pointer to a pointer, but the syntax is a little simpler. In the below code both foo1() and foo2() do the same thing, foo1() uses a reference and foo2() uses a pointer. Otherwise the two functions are indentical.

#include <iostream>
using namespace std;

void foo1(int& x)
// pointer to reference example
{
	int* p = &x;
	*p = 123;
}

void foo2(int* x)
// pointer to pointer example
{
	int** p = &x;
	**p = 345;
}

int main(int argc, char* argv[])
{
	int abc = 0;
	foo1(abc);
	cout << abc << "\n";
	abc = 0;
	foo2(&abc);
	cout << abc << "\n";
	return 0;
}

Picked from http://www.eternallyconfuzzled.com
A reference is not a pointer. A pointer is not a reference. End of story. Anyone who tries to explain a reference in terms of a pointer, or pointers in terms of a reference is only going to confuse people in the long run.

And btw, foo1 and foo2 are not at all equivalent.

Picked from http://www.eternallyconfuzzled.com
A reference is not a pointer. A pointer is not a reference. End of story. Anyone who tries to explain a reference in terms of a pointer, or pointers in terms of a reference is only going to confuse people in the long run.

you stated:

because you cannot take address of reference

I proved that incorrect. Just because you may not understand it does not mean it cannot be done.

Underneath the hood a c++ reference is really a pointer. If you look at the code produced by the compiler you will see that the arguments passed onto the stack for both foo1() and foo2() are identical -- both are c style pointers.

And a pointer most certainly is a reference -- in the more general sense. In c++ the phrase "pass by reference" can mean either by pointer or by c++ reference. There is only two (not three) ways to pass an object, either by reference or by value. Since we can both agree passing by value is not an issue here, then there is only one option left, pass by reference. And both foo1() and foo2() accomplish that.

FWIW:
http://parashift.com/c++-faq-lite/references.html#faq-8.1

Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object. It is not a pointer to the object, nor a copy of the object. It is the object.

I proved that incorrect.

Actually, it's the other way. The code you showed in counter of my statement is not what you claimed it to be. When I said you cannot take address of reference it means you can not take the address of reference itself.
If &x was a pointer to reference, then type of p should be int&* which is illegal.
Pointers to references are illegal and not allowed in C++ standard and if you still support the wrong notion then I am sorry to say you are plain wrong.

PS: I would like to clarify my previous statement.
foo1 and foo2 are not always equivalent. You can see the difference in code generated by turning off the optimisation.

If &x was a pointer to reference, then type of p should be int&* which is illegal.
.

That is not what I posted. I never claimed that was legal and you never posted that example until now.

If that is not what you mean then please post an example.

Finally, we come to agreement -- we were just talking about two different animals.:)

Underneath it all, a reference i to object x is typically the machine address of the object x
<snip>
A reference is the object. It is not a pointer to the object, nor a copy of the object. It is the object.

contridition there:eek: either a reference is a pointer or it isn't. If a reference is NOT a pointer then it would not be possible to change the value of the original object to which it references.

A reference is an object only in the sense that, like any other normal pointer, it is a container that holds the address of some other value.

int a = 5;
int& b = a;

b = 6;

In the above code, variable b is not the same as variable a, variable b is a container (has its own space on the stack) that holds the address of a, but it is not just another name for a (unless code optimization takes over, but that's a diferent story altogether).

Ancient Dragon:
You state that you can take address of a reference.
It is true that you can take the address of an expression formed of an identifier of a variable whose type is a reference type
In a sense, it is the address of the expression.
But can we say that it is taking the address of the reference.
If, by reference, we mean expression, that's right.
If, by reference, we mean the reference object, it is wrong.
Because, in fact, it yields the address of the object denoted by the reference.

Now, I think that your post #5 is very misleading.
You seem to say that foo1 and foo2, are, in a sense equivalent.

First, reference might be implemented in a very different way than the address of the object, though that's the implementation of a lot of compilers.

Now, deeming a well-defined x86-32 compiler (GCC 3.2.3), I can say that foo1 and foo2 are different beasts.
This compiler implements pointers as native (as in assembly) addresses of the object pointed-to.
And it implements references as the address of the object refered-to by the reference.

I compiled your code (with g++ -g) without optimizations:
Here is the disassembled code of foo1 (comments are mine)

0x4012d0 <_Z4foo1Ri>:   push   %ebp
0x4012d1 <_Z4foo1Ri+1>: mov    %esp,%ebp
0x4012d3 <_Z4foo1Ri+3>: sub    $0x4,%esp           // allocates space for p
0x4012d6 <_Z4foo1Ri+6>: mov    0x8(%ebp),%eax // moves address of the refered-to object in %eax
0x4012d9 <_Z4foo1Ri+9>: mov    %eax,0xfffffffc(%ebp) // and then, move it in the storage allocated for p, now p=&original_object
0x4012dc <_Z4foo1Ri+12>:        mov    0xfffffffc(%ebp),%eax // fetch the pointer into %eax
0x4012df <_Z4foo1Ri+15>:        movl   $0x7b,(%eax) // moves 0x7b in the pointed-to object.
0x4012e5 <_Z4foo1Ri+21>:        leave
0x4012e6 <_Z4foo1Ri+22>:        ret
0x4012e8 <_Z4foo2Pi>:   push   %ebp
0x4012e9 <_Z4foo2Pi+1>: mov    %esp,%ebp
0x4012eb <_Z4foo2Pi+3>: sub    $0x4,%esp // allocates space for p (pointer to pointer to int)
0x4012ee <_Z4foo2Pi+6>: lea    0x8(%ebp),%eax // moves the address of the pointer (which is on the stack) x in %eax
0x4012f1 <_Z4foo2Pi+9>: mov    %eax,0xfffffffc(%ebp) // then move this address in the storage allocated for p
0x4012f4 <_Z4foo2Pi+12>:        mov    0xfffffffc(%ebp),%eax // fetch the value of p in %eax; now %eax contains a pointer to a pointer (which is the x argument) to int (which is abc)
0x4012f7 <_Z4foo2Pi+15>:        mov    (%eax),%eax // now %eax is a pointer to int (which points to abc)
0x4012f9 <_Z4foo2Pi+17>:        movl   $0x159,(%eax) // moves $0x159 in abc
0x4012ff <_Z4foo2Pi+23>:        leave
0x401300 <_Z4foo2Pi+24>:        ret

You see that these codes are different.

In fact, the foo1 is much more equivalent to the following foo3:

void foo3(int* x) {
  int* p=x;
  *p=123;
}

int main() {
  int i=486;
  foo3(&i);
  return 0;
}

Now, I compiled foo3 (g++ -g)
The code of foo3 is:

Dump of assembler code for function _Z4foo3Pi:
0x4012d0 <_Z4foo3Pi>:   push   %ebp
0x4012d1 <_Z4foo3Pi+1>: mov    %esp,%ebp
0x4012d3 <_Z4foo3Pi+3>: sub    $0x4,%esp
0x4012d6 <_Z4foo3Pi+6>: mov    0x8(%ebp),%eax
0x4012d9 <_Z4foo3Pi+9>: mov    %eax,0xfffffffc(%ebp)
0x4012dc <_Z4foo3Pi+12>:        mov    0xfffffffc(%ebp),%eax
0x4012df <_Z4foo3Pi+15>:        movl   $0x7b,(%eax)
0x4012e5 <_Z4foo3Pi+21>:        leave
0x4012e6 <_Z4foo3Pi+22>:        ret

foo3 has the exact same code than foo1.

It doesn't mean that foo1 and foo3 are equivalent on all platforms (I know that references & pointers are different things, even if they are often implemented in a similar way).

But I think it is clear that foo1 and foo2 are different things.

Now, with optimizations... Since this code is dumb, the compiler can generate the same code:
With "g++ -g -O"

foo1 code is

0x4012d0 <_Z4foo1Ri>:   push   %ebp
0x4012d1 <_Z4foo1Ri+1>: mov    %esp,%ebp
0x4012d3 <_Z4foo1Ri+3>: mov    0x8(%ebp),%eax
0x4012d6 <_Z4foo1Ri+6>: movl   $0x7b,(%eax)
0x4012dc <_Z4foo1Ri+12>:        pop    %ebp
0x4012dd <_Z4foo1Ri+13>:        ret

foo2 code is:

0x4012de <_Z4foo2Pi>:   push   %ebp
0x4012df <_Z4foo2Pi+1>: mov    %esp,%ebp
0x4012e1 <_Z4foo2Pi+3>: mov    0x8(%ebp),%eax
0x4012e4 <_Z4foo2Pi+6>: movl   $0x159,(%eax)
0x4012ea <_Z4foo2Pi+12>:        pop    %ebp
0x4012eb <_Z4foo2Pi+13>:        ret

That is the same code (except that the constant $0x7b or $0x159 is not the same).
Because the compiler has been able to optimize out the intermediate p pointer-to-pointer variable in foo2.

With higher level of optimizations, inlining appears, and a lot of operations can be optimized out.

Hi Guys,

I still didn't get answer for my question.

By reference to pointer I mean this

int * & x;

Here x is a refernce to a pointer

In the same way pointer to a reference is not allowed in C++.
Somrthing like this

int & * x;

. This will throw an error saying "pointer to reference is illegal".

Now what my doubt is, if reference is just an alias to an object pointed to by it. Then what is the problem in creating a pointer to it ???

Hi Guys,

I still didn't get answer for my question.

By reference to pointer I mean this

int * & x;

Here x is a refernce to a pointer

This code is illegal because a reference has to be initialized not assigned. There are exceptions but in this case it has to be initialized.

In the same way pointer to a reference is not allowed in C++.

int & * x;

. This will throw an error saying "pointer to reference is illegal".

Now what my doubt is, if reference is just an alias to an object pointed to by it. Then what is the problem in creating a pointer to it ???

The Standard does not specify whether references need storage or not. So if there can't be storage for a reference, there is no meaning for pointers to a reference.

It is unspecified whether or not a reference requires storage

There shall be no references to references, no arrays of references, and no pointers to references. The declaration of a reference shall contain an initializer (dcl.init.ref) except when the declaration contains an explicit extern specifier (dcl.stc), is a class member (class.mem) declaration within a class declaration, or is the declaration of a parameter or a return type (dcl.fct);

commented: Very nice! +7

This explanation was very much usefull.Thank Wolf ..... Can you provide me the link to C++ standards.

This explanation was very much usefull.Thank Wolf ..... Can you provide me the link to C++ standards.

The C++ and C Standards are not free. The electronic version costs about 20$ and the hard copy cost 10 times more. You can download a draft copy which is free to download. It is not the same as the real thing, but will make do for the time being.

Thanks, once again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.