I know that use of const_cast
won't introduce undefined behaviour (i.e., it's safe to use), as long as the variable you're const_cast
ing wasn't originally defined as const
or if it was originally defined as const
you're not modifying it via its const_cast
ed alias.
However, It is also known that most STL containers (e.g., std::vector
, std::set
), allocate their internal buffers dynamically. Based on this fact I think that is impossible for a const
defined std::vector
to be placed in read-only memory.
Naturally, if the above holds I come to the assumption that such kind of STL containers even if they're defined as const
, e.g.,:
std::vector<int> const v;
const_cast
ing them and altering them via their const_cast
ed alias is legitimate and won't cause any undefined behavior.
Does the above assumption holds or I'm wrong?
The C++ standard explicitly points out that casting away const
for an object created via new const T
, and modifying it, is Undefined Behavior.
E.g., the C++11 standard contains this example in its §7.1.6.1/4:
const int* ciq = new const int (3); // initialized as required int* iq = const_cast<int*>(ciq); // cast required *iq = 4; // undefined: modifies a const object
Examples in the standard are non-normative, just examples, and can be wrong. For example, in C++03 nearly all examples that used <iostream>
were wrong (at that time it was formally necessary to also include <ostream>
, but that was not the intention of the committee), and the expression examples in C++03 §5/4 were wrong, saying the behavior was unspecified rather than undefined (which might have reflected an original intention). However, the above example is correct.
This shows that dynamically allocated memory needs not be mutable: that modifying it, can have Undefined Behavior.
However, when e.g. a std::string
is created, its allocation of a buffer (if any) occurs during execution of a constructor, at which point the object is not yet const
, and the buffer is not allocated as const
. So the buffer, if one is allocated, is not originally const
. But regarding this particular example the std::string
may use the small buffer optimization where it uses storage directly in the object, which would then be originally const
(potentially allocated in read only memory). And this goes to the rational for the rule that no originally const
object can be modified.
In addition to the read-only memory scenario, the rationale for UB includes that it can give compilers optimization possibilities.
As juanchopanza notes in a comment to the question,
” Optimizers use this to do all kind of crazy stuff that assumes
const
objects won't be modified.
Breaking the assumptions of the optimizer by modifying an originally const
object, can have disastrous and effectively unpredictable consequences.