A pointer is a variable holding a memory address which contains the value you want. For example:
int value = 42;
int* value_ptr = &value;
int access_via_ptr = *value_ptr;
A double pointer, or a pointer to pointer, is a variable holding an address of another pointer, which holds an address to the value you want. For example:
int value = 42;
int* value_ptr = &value;
int** value_ptr = &value_ptr;
int access_via_ptr_ptr = **value_ptr;
Why would you want to use **? One really useful way is in functions. You want to pass a pointer to a pointer, so that the function can setup the pointer address for you. For example:
#include <iostream>
void GetPtr(int** val_ptr_ptr, int init_contents)
{
// val_ptr_ptr should point to a pointer
// lets allocate it
*val_ptr_ptr = new int;
// de-reference ptr->ptr->val to initialize
// the contents
**val_ptr_ptr = init_contents;
}
int main(void)
{
int* val_ptr = NULL;
GetPtr(&val_ptr, 42);
std::cout << *val_ptr;
delete val_ptr;
return 0;
}
In this example we want a function to allocate memory. We want that memory to be stored in a pointer outside the function, so we can access it. We pass in an address of outside pointer, or a pointer to a pointer. We then assign the address inside the function.