What is a reference-to-pointer?

The above will be able to modify not only the pointed object, but also the pointer in itself. As an example, consider the below code:

void func(int*& ptr) {
    *ptr = 1;
    ptr = 0;
}

int main() {
    int x = 0;
    int* y = &x;
    func(y);
}

At the end of the execution, x has value 1 and y is 0 (as you can see).

Notice that for the sake of the example I’ve used 0 as a null pointer, but if you are using C++11 you should probably use nullptr instead (which does not have an overloaded operaror<< for std::ostream).


This concept can possibly be assimilated by taking a look at the following code:

template<class Type> using ptr = Type*;
ptr<int>& x;

or

std::unique_ptr<int>& x;

In these examples, x is a reference to a type (ptr<int> and then std::unique_ptr<int>), which just so happens to be a pointer/class with pointer semantic (operator* and operator->).


A possibly interesting digression can be made on the position of a const qualifier in the pointer. Consider these two instances:

  1. void func(const int*& ptr)
  2. void func(int*const& ptr)

Their meanings are:

  1. pointer by reference to a constant int.
  2. pointer by constant reference to an int.

And following the above analogy with ptr they would be:

  1. ptr<const int>&
  2. ptr<int> const&

Therefore the first will fail to execute *ptr = 1 in the body of the function (because the int is constant), but will happily execute ptr = 0.

The second will behave conversely, allowing *ptr = 1 (because the pointed int is not constant), while disallowing ptr = 0 (because the pointer is constant).

Of course, in the case of:

void func(const int*const& ptr)

which in the ptr analogy would be ptr<const int> const&, both of them wouldn’t be allowed.


And when to use this? Is it advisable to do this?

Like every feature, you’ll find its usefulness when you’ll need it. But just as a general idea, some people used it to reset the pointer after freeing a dynamically allocated resource (I’m not recommending this, see below).

Let’s take this example:

free_my_int(int*& ptr) {
    delete ptr;
    ptr = nullptr;
}

int* x = new int(42);
free_my_int(x);

At the end of the execution, x would be correctly freed and the pointer automatically set to nullptr (null pointer). This was done to prevent ugly segmentation faults or “pointer freed has not been allocated” error messages caused by a missing ptr = nullptr.

But with C++11 and C++14 there is very little use of pointers and even less of reference to pointers. Most of the things pointers where used for are not replaced with other standard construct (see std::optional, std::unique_ptr, std::shared_ptr or std::reference_wrapper for example).

Leave a Comment