Pointers to pointers normally ought not be used. Instead, a class should be declared, which has a member variable of the pointer type. This improves the readability of the code and encourages data abstraction. By improving the readability of code, the probability of failure is reduced. One exception to this rule is represented by functions which provide interfaces to other languages (such as C). These are likely to only allow pre-defined data types to be used as arguments in the interface, in which case pointers to pointers are needed. Another example is the second argument to the main function, which must have the type char*[].
A function which changes the value of a pointer that is provided as an argument, should declare the argument as having the type reference to pointer (e.g. char*&). See Rec. 42!
typedef is a good way of making code more easily maintainable and portable. See chapter 18.1, Port.Rec.1. Another reason to use typedef is that the readability of the code is improved. If pointers to functions are used, the resulting code can be almost unreadable. By making a type declaration for the function type, this is avoided.
Function pointers can be used as ordinary functions; they do not need to be dereferenced .
Example 45 Different comparisons of pointers
char* sp = new char[100] if ( !sp ) cout << "New failed!" << endl; // No! if ( sp == 0 ) cout << "New failed!" << endl; // Best if ( sp == NULL ) cout << "New failed!" << endl; // ERROR sometimes !!!Example 46 Pointers to pointers are often unnecessary
#include <iostream.h>
void print_mij(int** m, int dim1, int dim2)
{
  for (int i = 0; i < dim1; i++)
  {
      for (int j = 0; j < dim2; j++ )
          cout << " " << ((int*)m)[i*dim2+j]
      cout << endl
  }
}
// Could be written as:
class Int_Matrix
{
public:
  Int_Matrix(int dim1, int dim2)
  int value(int,int) const
  int dim1() const
  int dim2() const
  // ..
}
void print_Mij(Int_Matrix m)
{
  for (int i = 0; i < m.dim1(); i++)
  {
      for (int j = 0; j < m.dim2(); j++ )
          cout << " " << m.value(i,j)
      cout << endl
  }
}
Example 47 Complicated declarations
// func1 is a function: int -> (function : const char* -> int) // i.e. a function having one argument of type int and returning // a pointer to a function having one argument of type const char* // and returning an int. int (*func1(int))(const char*) // func1 of the same type as func2 typedef int FTYPE(const char*) FTYPE* func2(int) int (*(*func1p)(int))(const char*) = func2 // Realistic example from signal.h void (*signal(int,void (*)(int)))(int);Example 48 Syntax simplification of function pointers using a typedef
#include <math.h>
// Ordinary messy way of declaring pointers to functions:
// double ( *mathFunc ) ( double ) = sqrt
// With a typedef, life is filled with happiness (chinese proverb):
typedef double MathFuncType( double )
MathFuncType* mathFunc = sqrt
void
main()
{
  // You can invoke the funktion in an easy or complicated way
  double returnValue1 = mathFunc( 23.0 ); // Easy way
  double returnValue2 = ( *mathFunc )( 23.0 ); // No! OK but complicated
}