What can a 'const' method change?
Without explicitly casting away constness, a const
member function can change:
mutable
data members, and
- any data the class has non-
const
access to, irrespective of whether that data's accessible:
- via member variables that are pointers or references,
- via pointers or references passed as function arguments,
- via pointers or references returned by functions,
- directly in the namespace or class (for static members) containing it.
These restrictions apply to operations of data members and bases (in the OO sense) too. More explicitly, a const
member function operating on *this
's data members or bases, when they're of class
/struct
/union
type, can only call their const
member functions (if any), and can only write to their mutable
data members (if any).
(A const
member function can also change any non-const
local variables and by-value parameters, but I know that's not what you're interested in).
const
data members can call other const
member functions, which will have these same abilities and restrictions.
Eg. if the instance variables are pointers, does it mean that the pointers are not changed, or also that the memory to which they point is not changed?
It means the pointers can't be (easily/accidentally) changed. It does not mean that the pointed-to memory can't be changed.
What you've stumbled on is the logical incorrectness of a const
function changing pointed-to or referenced data conceptually owned by the object. As you've found, the compiler doesn't enforce the const
correctness you may want or expect here. That's a bit dangerous, but means constness doesn't need to be explicitly removed for pointers/references to other objects which may be changed as a side-effect of the const
function. For example, a logging object. (Typically, such objects are not logically "owned" by the object whose const
function is operating on them.) The key point is that the compiler can't reliably distinguish the type of logical ownership an object has over pointed-to data, so it's got to guess one way or the other and allow the programmer to either override, or not be protected by const
-ness. C++ forgoes the protection.
Interesting, I've heard Walter Bright's D language flips this default, making pointed-to data const
by default in const
functions. That seems safer to me, though it's hard to imagine how often one would end up needing to explicitly cast away constness to allow wanted side-effects, and whether that would feel satisfyingly precise or annoyingly verbose.