Gotcha #6: Misunderstanding Const
The concept of constness in C++ is simple, but it doesn't necessarily correspond to our preconceived notions of a constant.
First, note the difference between a variable declared const and a literal:
int i = 12;
const int ci = 12;
The integer literal 12 is not a const. It's a literal. It has no address, and its value never changes. The integer i is an object. It has an address, and its value is variable. The const integer ci is also an object. It has an address, though (in this case) its value may not vary.
We say that i and ci may be used as lvalues, whereas the literal 12 may only be an rvalue. This terminology comes from the pseudoexpression L = R, indicating that an lvalue may appear as the left argument of an assignment and an rvalue may appear only as the right argument of an assignment. However, this definition is not perfectly applicable in the case of C++ or standard C, where ci is an lvalue but may not be assigned to because it's a nonmodifiable lvalue. Consider lvalues as locations that may hold values, and rvalues as simple values with no associated address:
int *ip1 = &12; // error!
12 = 13; // error!
const int *ip2 = &ci; // OK
ci = 13; // error!
It's best to consider const, in the declaration of ip2 above, a restriction on how we may manipulate ci through ip2 rather than on how ci may be manipulated in general. Consider declaring a pointer to a const:
const int *ip3 = &i;
i = 10; // OK
*ip3 = 10; // error!
Here, we have a pointer to a constant integer that refers to a non-constant integer. The use of const in this case is simply a restriction on how ip3 may be used. It doesn't imply that i won't change, only that we may not change it through ip3. Even subtler are combinations of const and volatile:
extern const volatile time_t clock;
The presence of the const qualifier indicates that we're not allowed to modify the variable clock, but the presence of the volatile qualifier indicates that the value of clock may (that is, will) change nonetheless.
|