C++: Why is const_cast evil?

c++, casting, const-cast, constants, pointers

Solution

Because you're thwarting the purpose of `const`, which is to keep you from modifying the argument. So if you cast away the `const`ness of something, it's pointless and bloating your code, and it lets you break promises that you made to the user of the function that you won't modify the argument.

In addition, using `const_cast` can cause undefined behaviour. Consider this code:

SysOscillatorBase<int> src;
const SysOscillatorBase<int> src2;

...

aFieldTransformer.setOscillator(src);
aFieldTransformer.setOscillator(src2);

In the first call, all is well. You can cast away the `const`ness of an object that is not really `const` and modify it fine. However, in the second call, in `setOscillator` you are casting away the `const`ness of a truly `const` object. If you ever happen to modify that object in there anywhere, you are causing undefined behaviour by modifying an object that really is `const`. Since you can't tell whether an object marked `const` is really `const` where it was declared, you should just never use `const_cast` unless you are sure you'll never ever mutate the object ever. And if you won't, what's the point?

In your example code, you're storing a non-`const` pointer to an object that might be `const`, which indicates you intend to mutate the object (else why not just store a pointer to `const`?). That might cause undefined behaviour.

Also, doing it that way lets people pass a temporary to your function:

blah.setOscillator(SysOscillatorBase<int>()); // compiles

And then you're storing a pointer to a temporary which will be invalid when the function returns1. You don't have this problem if you take a non-`const` reference.

On the other hand, if I don't use const_cast, the code won't compile.

Then change your code, don't add a cast to make it work. The compiler is not compiling it for a reason. Now that you know the reasons, you can make your `vector` hold pointers to `const` instead of casting a square hole into a round one to fit your peg.

So, all around, it would be better to just have your method accept a non-`const` reference instead, and using `const_cast` is almost never a good idea.

1 Actually when the expression in which the function was called ends.

Problem

I keep hearing this statement, while I can't really find the reason why const_cast is evil. In the following example: ``` template <typename T> void OscillatorToFieldTransformer<T>::setOscillator(const SysOscillatorBase<T> &src) { oscillatorSrc = const_cast<SysOscillatorBase<T>*>(&src); } ``` I'm using a reference, and by using const, I'm protecting my reference from being changed. On the other hand, if I don't use const_cast, the code won't compile. Why would const_cast be bad here? The same applies to the following example: ``` template <typename T> void SysSystemBase<T>::addOscillator(const SysOscillatorBase<T> &src) { bool alreadyThere = 0; for(unsigned long i = 0; i < oscillators.size(); i++) { if(&src == oscillators[i]) { alreadyThere = 1; break; } } if(!alreadyThere) { oscillators.push_back(const_cast<SysOscillatorBase<T>*>(&src)); } } ``` Please provide me some examples, in which I can see how it's a bad idea/unprofessional to use a const_cast. Thank you for any efforts :)

Original source

Related problems