Difference between pointer to a reference and reference to a pointer

Solution 1:

First, a reference to a pointer is like a reference to any other variable:

void fun(int*& ref_to_ptr)
{
    ref_to_ptr = 0; // set the "passed" pointer to 0
    // if the pointer is not passed by ref,
    // then only the copy(parameter) you received is set to 0,
    // but the original pointer(outside the function) is not affected.
}

A pointer to reference is illegal in C++, because -unlike a pointer- a reference is just a concept that allows the programmer to make aliases of something else. A pointer is a place in memory that has the address of something else, but a reference is NOT.

Now the last point might not be crystal clear, if you insist on dealing with references as pointers. e.g.:

int x;
int& rx = x; // from now on, rx is just like x.
// Unlike pointers, refs are not real objects in memory.
int* p = &x; // Ok
int* pr = ℞ // OK! but remember that rx is just x!
// i.e. rx is not something that exists alone, it has to refer to something else.
if( p == pr ) // true!
{ ... }

As you can see from the above code, when we use the reference, we are not dealing with something separated from what it refers to. So, the address of a reference is just the address of what it refers to. Thats why there is no such thing called the address of the reference in terms of what you are talking about.

Solution 2:

Pointer to a pointer

A pointer in C++ is just a value which stores a memory location (generally as a 32-bit value).

Let's say you had an user input integer value (78 == 0x4E in hex).

It would be stored in memory in a similar way to this (I'm purposely simplifying things for this example):

Memory address    Value
0x12345678        0x0000004E

If you wanted to create a "pointer" to this value, it would look like this in memory:

Memory address    Value
0x22334455        0x12345678

At memory address 0x22334455 you now have a "pointer" whose value is 0x12345678, or the memory address of where the user input integer value (0x4E) is stored.

Let's say you wanted to create a "pointer" to this pointer value. It would look like this:

Memory address    Value
0x11335577        0x22334455

You now have a new "pointer" value in memory which is storing the memory address of the previously-defined pointer value.

Pointers can be created like this indefinitely - the key is remembering that a pointer is just another value that the compiler interprets as a memory location (and it provides various access semantics such as * and -> which are special to "pointer" types).

Reference to a pointer

A reference can be thought of as a view, or alias, on to another real object. When you create a reference to a pointer called myReference, you are simply defining a new name called myReference which can be used to access the pointer which you have previous defined in memory.

Internally, references are implemented using pointers, but this is beyond the scope of your question.

References have restrictions over other types in C++ - for example, you must always initialize a reference to "refer" to a real object when you create it, while a pointer may point to memory which is invalid, or uninitialised.

Pointer to a reference

This doesn't exist. As stated earlier, a reference is merely an alias to another object. You can't "point" to a reference, because it isn't an object in itself but merely another name for a real object.

Of course, you can have a pointer to the object that a reference is referring to. But now we are back in vanilla pointer territory.

Note about parameters

When you pass a parameter by value to a method or routine, you are essentially passing a "copy" of the object to the method. Any changes you make to the value within the routine will be lost when the routine returns, because the parameter will be treated as a local variable in the context of the routine.

If you want to modify a parameter which is passed in so the client (calling) code can access the change, you must pass the parameter by pointer or by reference.

For example:

void myMethod(int myValue)
{
    // NOTE: This change will be lost to the caller!
    myValue = 5;
}

void myMethod2(int* myValue)
{
    // Correct way of modifying pointer parameter value
    *myValue = 5;
}

void myMethod3(int& myValue)
{
    // Correct way of modifying reference parameter value
    myValue = 5;
}

Let's now say that your method wants to allocate memory for a pointer. You could be tempted to do this:

void myMethod4(int* myValue)
{
    // Warning: You will lose the address of the allocated
    // memory when you return!
    myValue = new int[5];
}

But remember, you are modifying the copy of the pointer value here, not the real pointer value. Since you are wanting to modify the pointer in this routine, and not the value that the pointer "points" to, you need to pass it in as a "pointer to a pointer" or a "reference to a pointer":

void myMethod5(int** myValue)
{
    // Correct way of allocating memory in a method
    // via pointer-to-pointer
    *myValue = new int[5];
}

void myMethod6(int*& myValue)
{
    // Correct way of allocating memory in a method
    // via reference-to-pointer
    myValue = new int[5];
}

In these bottom 2 examples, the code which is calling myMethod5 and myMethod6 will correctly get the memory address of the newly-allocated memory via the myValue parameter pointer or reference.

Solution 3:

There is no such thing as a pointer to a reference.

Solution 4:

A reference is an abstraction away from pointers. References are a bit harder to screw up, especially for novices, and are a bit more high level.

You don't need references. You can always use pointers. However, sometimes code can be easier to read with them.

A typical beginner example is a linked list. Imagine you have a variable called "list" that contains a pointer to the first one. If you wanted to add something to the head, you'd need to give your add() a double pointer, since it needs to be able to modify "head". However, you can use a reference to a pointer instead. Here, we want to use pointers in the list itself since we'll be mutating them, but the add() function will be clearer if we pass in a reference to the head of the list instead of a double pointer.

They're simply a style choice. If you're working on a larger project, you should go with the style of the project. If not, you can use whatever you feel is preferable. You should, however, be comfortable using all styles if you even hope to be a mildly successful C++ programmer.

It is also worthwhile that you can't have a pointer to a reference. This is because references are really just another name for another variable, which may be in some other scope. Having a pointer to a reference doesn't make sense. What you'd really want is just a pointer to whatever the original data was, no references involved.

Solution 5:

It is important to note that although a reference is not an object and therefore does not have an accessible address, a reference can be contained within an object and the containing object does have an address.

struct contains_ref
{
     int& ref;
     contains_ref(int& target) : ref(target) {}
};

The "reference is an alias" explanation is not incorrect, but is often accompanied by misleading claims. A reference is not equivalent to the original object. It has its own lifetime, determined by the scope or object that contains it, and not the object it refers to. And a reference can outlive an object and be used to refer to a new object created at the same address.

Treat a reference as what it really is -- an abstraction around a pointer that excludes null as a valid value, and prevents reseating1 -- and not something magic. The only unusual property of a reference that isn't derived from its pointer nature is lifetime extension of temporaries.


1Actually this is a consequence of the fact that C++ doesn't provide any syntax for referring to the reference itself rather than its target. All operators, including the assignment operator, are simply applied to the target.