[ fromfile: constptrs.xml id: constptrs ]
Suppose that you have a pointer ptr
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 can be imposed with const
.
If you want to make sure that ptr
cannot point to any other memory location
(i.e., cannot store a different address), you 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 you want to make sure that the value of vbl
cannot be changed by
dereferencing ptr
, you 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 you want to impose both kinds of protection you 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.30 demonstrates the two kinds of protection.
Example 1.30. 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.5 shows two snapshots of memory at the noted spots in Example 1.30, 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.5).
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |