Sept. 13, 2008, 3:05 p.m.
posted by nogood
Item 8. Pointers to PointersIt's legal to declare a pointer to a pointer. This is what the C++ standard calls a "multilevel" pointer. int *pi; // a ptr int **ppi; // a two-level multilevel ptr int ***pppi; // a three-level multilevel ptr Although it's rare to encounter multilevel pointers with more than two levels, we do see pointers to pointers in two common situations. The first is when we declare an array of pointers. Shape *picture[MAX]; // array of ptr to Shape Because an array name decays into a pointer to its first element (see Array Formal Arguments [6, 17]), the name of an array of pointers is also a pointer to a pointer. Shape **pic1 = picture; We most often see this usage in the implementation of a class that manages a buffer of pointers:
template <typename T>
class PtrVector {
public:
explicit PtrVector( size_t capacity )
: buf_(new T *[capacity]), cap_(capacity), size_(0) {}
//...
private:
T **buf_; // ptr to array of ptr to T
size_t cap_; // capacity
size_t size_; // size
};
//...
PtrVector<Shape> pic2( MAX );
As the implementation of PtrVector implies, pointers to pointers can be complex and are best kept hidden. The second common use of multilevel pointers occurs when a function needs to change the value of a pointer that is passed to it. Consider the following function that moves a pointer to refer to the next occurrence of a character in a string: void scanTo( const char **p, char c ) { while( **p && **p != c ) ++*p; } The first argument to scanTo is a pointer to the pointer whose value we want to change. That means we have to pass the address of the pointer: char s[] = "Hello, World!"; const char *cp = s; scanTo( &cp, ',' ); // move cp to first comma This usage is reasonable in C, but in C++ it is more conventional, simpler, and safer to use a reference to a pointer as a function argument rather than a pointer to a pointer.
void scanTo( const char *&p, char c ) {
while( *p && *p != c )
++p;
}
//...
char s[] = "Hello, World!";
const char *cp = s;
scanTo( cp, ',' );
In C++, using a reference to pointer function argument should nearly always be preferred to a pointer to pointer argument. A common misconception is that conversions that apply to pointers also apply to pointers to pointers. This is not the case. For instance, we know that a pointer to a derived class can be converted to a pointer to its public base class: Circle *c = new Circle; Shape *s = c; // fine... Because a Circle is-a Shape, it follows that a pointer to a Circle is also a pointer to a Shape. However, a pointer to a pointer to a Circle is not a pointer to a pointer to a Shape:
Circle **cc = &c;
Shape **ss = cc; // error!
The same confusion often occurs when const is involved. We know that it's legal to convert a pointer to non-const to a pointer to const (see Const Pointers and Pointers to Const [7, 21]), but we may not convert a pointer to pointer to non-const to a pointer to pointer to const:
char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char **ps = a; // error!
|
- Comment