C++:为什么 const_cast 是邪恶的?
我一直听到这种说法,虽然我实在找不到 const_cast 是邪恶的原因.
I keep hearing this statement, while I can't really find the reason why const_cast is evil.
在下面的例子中:
template <typename T>
void OscillatorToFieldTransformer<T>::setOscillator(const SysOscillatorBase<T> &src)
{
oscillatorSrc = const_cast<SysOscillatorBase<T>*>(&src);
}
我正在使用引用,并且通过使用 const,我可以保护我的引用不被更改.另一方面,如果我不使用 const_cast,代码将无法编译.为什么 const_cast 在这里会很糟糕?
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?
同样适用于以下示例:
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));
}
}
请给我提供一些例子,我可以从中看出使用 const_cast 是个坏主意/不专业.
Please provide me some examples, in which I can see how it's a bad idea/unprofessional to use a const_cast.
感谢您的任何努力:)
推荐答案
因为你在阻挠 const
的目的,是为了防止你修改参数.因此,如果你抛弃了某些东西的 const
性质,它就会毫无意义并且会使你的代码变得臃肿,它会让你违背你对函数用户做出的不会修改参数的承诺.
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.
此外,使用 const_cast
会导致未定义的行为.考虑这个代码:
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);
在第一次通话中,一切都很好.你可以抛弃一个不是真正 const
的对象的 const
ness 并对其进行很好的修改.然而,在第二次调用中,在 setOscillator
中,您正在抛弃真正的 const
对象的 const
ness.如果你碰巧在那里的任何地方修改了那个对象,你就会通过修改一个真正是 const
的对象来导致未定义行为.由于您无法判断标记为 const
的对象是否真的 const
声明它的位置,因此您永远不应该使用 const_cast
除非你确定你永远不会改变对象.如果你不这样做,那又有什么意义呢?
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?
在您的示例代码中,您存储了一个指向可能是 const
的对象的非 const
指针,这表明您打算改变该对象(否则为什么不只是存储一个指向 const
的指针?).这可能会导致未定义的行为.
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
然后您将存储一个指向临时对象的指针,当函数返回1时该指针将无效.如果您采用非const
引用,则不会遇到此问题.
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.
另一方面,如果我不使用 const_cast,代码将无法编译.
On the other hand, if I don't use const_cast, the code won't compile.
然后更改您的代码,不要添加演员表以使其工作.编译器没有编译它是有原因的.现在您知道原因了,您可以让 vector
指向 const
的指针,而不是将一个方孔变成圆形以适合您的挂钩.
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.
因此,在所有情况下,最好让您的方法接受非 const
引用,而使用 const_cast
几乎从来都不是一个好主意.
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 实际上是在调用函数的表达式结束时.
1 Actually when the expression in which the function was called ends.
相关文章