C++ standard says that modifying an object originally declared const
is undefined behavior. But then how do constructors and destructors operate?
The standard explicitly allows constructors and destructors to deal with const
objects. from 12.1/4 "Constructors":
A constructor can be invoked for a
const
,volatile
orconst volatile
object. ...const
andvolatile
semantics (7.1.5.1) are not applied on an object under construction. Such semantics only come into effect once the constructor for the most derived object (1.8) ends.
And 12.4/2 "Destructors":
A destructor can be invoked for a
const
,volatile
orconst volatile
object. ...const
andvolatile
semantics (7.1.5.1) are not applied on an object under destruction. Such semantics stop being into effect once the destructor for the most derived object (1.8) starts.
As background, Stroustrup says in "Design and Evolution of C++" (13.3.2 Refinement of the Defintion of const
):
To ensure that some, but not all,
const
objects could be placed read-only memory (ROM), I adopted the rule that any object that has a constructor (that is, required runtime initialization) can't be place in ROM, but otherconst
objects can....
An object declared
const
is considered immutable from the completion of the constructor until the start of its destructor. The result of a write to the object between those points is deemed undefined.When originally designing
const
, I remember arguing that the idealconst
would be an object that is writable until the constructor had run, then becomes read-only by some hardware magic, and finally upon the entry into the destructor becomes writable again. One could imagine a tagged architecture that actually worked this way. Such an implementation would cause a run-time error if someone could write to an object definedconst
. On the other hand, someone could write to an object not definedconst
that had been passed as aconst
reference or pointer. In both cases, the user would have to cast awayconst
first. The implication of this view is that casting awayconst
for an object that was originally definedconst
and then writing to it is at best undefined, whereas doing the same to an object that wasn't originally definedconst
is legal and well defined.Note that with this refinement of the rules, the meaning of
const
doesn't depend on whether a type has a constructor or not; in principle, they all do. Any object declaredconst
now may be placed in ROM, be placed in code segments, be protected by access control, etc., to ensure that it doesn't mutate after receiving its initial value. Such protection is not required, however, because current systems cannot in general protect everyconst
from every form of corruption.