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. This means there are two possible layers of protection that we might want to impose with const:
Type* const ptr = &vbl; Type* const ptr(&vbl);
The pointer is a const but the addressed object can be changed.
const Type* ptr = &vbl; const Type* ptr(&vbl);
In this case, the addressed object is a constant but the pointer is not.
In addition, 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 */
A short program that demonstrates the two kinds of protection is shown in Example 1.22.
Example 1.22. src/constptr/constptr.cpp
#include using namespace std; int main() { int m1(11), m2(13); const int* n1(&m1); int* const n2(&m2); // First snapshot cout << "n1 = " << n1 << ' ' << *n1 << ' ' << "n2 = " << n2 << ' ' << *n2 << endl; n1 = &m2; //*n1 = 15; <-- 1 m1 = 17; <-- 2 //n2 = &m1; <-- 3 *n2 = 16; <-- 4 // Second snapshot cout << "n1 = " << n1 << ' ' << *n1 << ' ' << "n2 = " << n2 << ' ' << *n2 << endl; return 0; } Output: src/constptr> g++ constptr.cpp src/constptr> ./a.out n1 = 0xbffff504 11 n2 = 0xbffff500 13 n1 = 0xbffff500 16 n2 = 0xbffff500 16 src/constptr>
|
Figure 1.2 shows two snapshots of memory that may help to clarify what is happening when the program runs. Notice that the program produces a memory leak.
Figure 1.2. Two snapshots of memory showing what the program in Example 1.2 produces
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; // OK const int* p2 = &a; // OK int* p3 = &c; // error *p3 = 5; // error
It is good programming practice to use const to protect pointer and reference parameters that 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 (see Section 5.6).
Part I: Introduction to C++ and Qt 4
C++ Introduction
Classes
Introduction to Qt
Lists
Functions
Inheritance and Polymorphism
Part II: Higher-Level Programming
Libraries
Introduction to Design Patterns
QObject
Generics and Containers
Qt GUI Widgets
Concurrency
Validation and Regular Expressions
Parsing XML
Meta Objects, Properties, and Reflective Programming
More Design Patterns
Models and Views
Qt SQL Classes
Part III: C++ Language Reference
Types and Expressions
Scope and Storage Class
Statements and Control Structures
Memory Access
Chapter Summary
Inheritance in Detail
Miscellaneous Topics
Part IV: Programming Assignments
MP3 Jukebox Assignments
Part V: Appendices
MP3 Jukebox Assignments
Bibliography
MP3 Jukebox Assignments