[ fromfile: constptrs.xml id: constptrs ]
Suppose that we have a pointer ptr that is storing the address of a variable vbl:
Type* ptr = &vbl;
When using a pointer, two objects are involved: the pointer itself and the object pointed to. That means
there are three possible layers of protection that we might want to impose with const.
If we want to make sure that ptr cannot point to any other memory location (i.e., cannot store a different address), we can write it one of two ways:
Type* const ptr = &vbl; Type* const ptr(&vbl);
The pointer is a const but the addressed object can be changed.
If we want to make sure that the value of vbl cannot be changed by dereferencing ptr, we can write it in two ways:
const Type* ptr = &vbl; const Type* ptr(&vbl);
In this case, the addressed object is a constant but the pointer is not.
If we want to impose both kinds of protection we can write:
const Type* const ptr = &vbl; const Type* const ptr(&vbl);
Here is a good way to remember which is which: Read each of the following definitions from right to left (starting with the defined variable).
const char* x = &p; /* x is a pointer to const char */ char* const y = &q; /* y is a const pointer to char */ const char* const z = &r; /* z is a const pointer to a const char */
Example 1.26 demonstrates the two kinds of protection.
Example 1.26. src/constptr/constptr.cpp
#include <QTextStream> int main() { QTextStream cout(stdout); int m1(11), m2(13); const int* n1(&m1); int* const n2(&m2); // First snapshot cout << "n1 = " << n1 << '\t' << *n1 << '\n' << "n2 = " << n2 << '\t' << *n2 << endl; n1 = &m2; //*n1 = 15;m1 = 17;
//n2 = &m1;
*n2 = 16;
// Second snapshot cout << "n1 = " << n1 << '\t' << *n1 << '\n' << "n2 = " << n2 << '\t' << *n2 << endl; return 0; }
Output:
src/constptr> ./constptr n1 = 0xbffff504 11 n2 = 0xbffff500 13 n1 = 0xbffff500 16 n2 = 0xbffff500 16 src/constptr>
Figure 1.4 shows two snapshots of memory at the noted spots in Example 1.26, to help clarify what is happening when the program runs. Notice that the program produces a memory leak.
An object that is read-only when accessed through one pointer may be changeable when accessed through another pointer. This fact is commonly exploited in the design of functions.
char* strcpy(char* dst, const char* src); // strcpy cannot change *src
It is okay to assign the address of a variable to a pointer to const.
It is an error to assign the address of a const object to an unrestricted (i.e., non-const) pointer variable
because that would allow the const object's value to be changed.
int a = 1; const int c = 2; const int* p1 = &c; // okay const int* p2 = &a; // okay int* p3 = &c; // error *p3 = 5; // error
It is good programming practice to use const to protect pointer and reference parameters which do not need to be altered by the action of a function.
Read-only reference parameters provide the power and efficiency of pass-by-reference with the safety of pass-by-value (Section 5.6).
| Generated: $Date: 2009-09-08 12:15:32 -0400 (Tue, 08 Sep 2009) $ | © 2009 Alan Ezust and Paul Ezust. |