Consider the following C function:
void giveme(char **p) {
*p = "Hello, World!";
}
Which gives you a string. If we were giving the string as a return value, we would have used just a pointer-to-char: char *giveme()
, but since we use an out parameter we must have a pointer to whatever it is we want to return. In this case a pointer to a pointer to char.
One case where you'd meet such code is COM, where the basic function QueryInterface
is defined as:
HRESULT QueryInterface(
[in] REFIID riid,
[out] void **ppvObject
);
In the following code we want get an IUnknown
somehow, and want to set the pointer pWhatever
to point to the IWhatever
interface of our object. We call QueryInterface
the following way:
IUnknown *pUnk = getIUnknownFromWherever();
IWhatever *pWhatever = NULL;
HRESULT hr;
hr = pUnk->QueryInterface(IID_IWHATEVER, &pWhatever);
Since we want QueryInterface
to change the pointer, rather than the pointee (the object it point to) we need to give it the address of the pointer.
Now, the whole point of C++ references is to make life easier in some common scenarios when pointers are used in C. One of them is out parameters. So, the previous two code fragments in C++ could have been:
// Assume IUnknown::QueryInterface was defined as:
HRESULT QueryInterface(
[in] REFIID riid,
[out] void *&ppvObject
);
// Now using it could have been somewhat less verbose
// and error prone thanks to references:
IUnknown *pUnk = getIUnknownFromWherever();
IWhatever *pWhatever = NULL;
HRESULT hr;
hr = pUnk->QueryInterface(IID_IWHATEVER, pWhatever);
// We're not passing pWhatever, but rather a reference to
// it - but since it's a C++ reference rather than a pointer,
// we don't need to explicitly use the address-of(&) operator
And that's it. The point of passing a pointer as reference is basically the same as passing any parameter as non-const reference - have the callee change it. Here we want a pointer (rather than an int or a double) changed so we pass a reference to a pointer.