I read on the wikipedia page for Null_pointer that Bjarne Stroustrup suggested defining NULL as
const int NULL = 0;
if “you feel you must define NULL.” I instantly thought, hey.. wait a minute, what about const_cast?
After some experimenting, I found that
int main() {
const int MyNull = 0;
const int* ToNull = &MyNull;
int* myptr = const_cast<int*>(ToNull);
*myptr = 5;
printf("MyNull is %d\n", MyNull);
return 0;
}
would print “MyNull is 0”, but if I make the const int belong to a class:
class test {
public:
test() : p(0) { }
const int p;
};
int main() {
test t;
const int* pptr = &(t.p);
int* myptr = const_cast<int*>(pptr);
*myptr = 5;
printf("t.p is %d\n", t.p);
return 0;
}
then it prints “t.p is 5”!
Why is there a difference between the two? Why is “*myptr = 5;” silently failing in my first example, and what action is it performing, if any?
Your code is modifying a variable declared constant so anything can happen. Discussing why a certain thing happens instead of another one is completely pointless unless you are discussing about unportable compiler internals issues… from a C++ point of view that code simply doesn’t have any sense.
About
const_castone important thing to understand is that const cast is not for messing about variables declared constant but about references and pointers declared constant.In C++ a
const int *is often understood to be a “pointer to a constant integer” while this description is completely wrong. For the compiler it’s instead something quite different: a “pointer that cannot be used for writing to an integer object”.This may apparently seem a minor difference but indeed is a huge one because
The “constness” is a property of the pointer, not of the pointed-to object.
Nothing is said about the fact that the pointed to object is constant or not.
The word “constant” has nothing to do with the meaning (this is why I think that using
constit was a bad naming choice).const int *is not talking about constness of anything but only about “read only” or “read/write”.const_castallows you to convert between pointers and references that can be used for writing and pointer or references that cannot because they are “read only”. The pointed to object is never part of this process and the standard simply says that it’s legal to take a const pointer and using it for writing after “casting away” const-ness but only if the pointed to object has not been declared constant.Constness of a pointer and a reference never affects the machine code that will be generated by a compiler (another common misconception is that a compiler can produce better code if const references and pointers are used, but this is total bogus… for the optimizer a const reference and a const pointer are just a reference and a pointer).
Constness of pointers and references has been introduced to help programmers, not optmizers (btw I think that this alleged help for programmers is also quite questionable, but that’s another story).
const_castis a weapon that helps programmers fighting with broken const-ness declarations of pointers and references (e.g. in libraries) and with the broken very concept of constness of references and pointers (beforemutablefor example casting away constness was the only reasonable solution in many real life programs).Misunderstanding of what is a const reference is also at the base of a very common C++ antipattern (used even in the standard library) that says that passing a const reference is a smart way to pass a value. See this answer for more details.