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 🙂
Because you’re thwarting the purpose of
const, which is to keep you from modifying the argument. So if you cast away theconstness 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_castcan cause undefined behaviour. Consider this code:In the first call, all is well. You can cast away the
constness of an object that is not reallyconstand modify it fine. However, in the second call, insetOscillatoryou are casting away theconstness of a trulyconstobject. If you ever happen to modify that object in there anywhere, you are causing undefined behaviour by modifying an object that really isconst. Since you can’t tell whether an object markedconstis reallyconstwhere it was declared, you should just never useconst_castunless 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-
constpointer to an object that might beconst, which indicates you intend to mutate the object (else why not just store a pointer toconst?). That might cause undefined behaviour.Also, doing it that way lets people pass a temporary to your function:
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-
constreference.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
vectorhold pointers toconstinstead 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-
constreference instead, and usingconst_castis almost never a good idea.1 Actually when the expression in which the function was called ends.