需要对 C 风格、重新解释和 const 强制转换进行澄清
我是否正确地假设 C 风格的强制转换(不鼓励这样做)只不过是 reinterpret_casts?使用后者在视觉上引人注目,并且在寻找令人讨厌的强制转换时易于搜索,因此建议使用它而不是 C 风格的强制转换?
如果使用 const_cast 抛弃 const 并写入原始 const 对象是未定义的,那么 const_cast 的目的是什么?
注意:我知道 Bjarne 正确地谴责了转换操作,认为它们是不安全的,甚至达到了“一个丑陋操作应该有一个丑陋的语法形式”的程度。因此,C++ 中的转换运算符显得冗长。所以我会尽量减少它们的使用。承诺。 :)
Am I right in assuming that C-style casts (which are discouraged) are nothing but reinterpret_casts? Using the latter is visually striking and easy to search when looking for nasty casts, and hence it's recommended over C-style casts?
If casting away const using const_cast and writing to a originally const object is undefined, what is the purpose of const_cast?
Note: I know that Bjarne rightly condemns casting operations that they are unsafe and even goes to the extent of stating "An ugly operation should have an ugly syntactic form." and hence the verbosity of casting operators in C++. So I'll try to minimize their usage. Promise. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不会。AC 强制转换可以执行与
const_cast
、static_cast
、reinterpret_cast
或其组合等效的操作。如果这还不够,它还可以做至少一个新演员组合根本无法做到的小技巧!如果原始变量是在没有
const
的情况下定义的,则可以使用const_cast
来定义结果,但您拥有的只是一个const
指针或对该对象的引用。 OTOH,如果您认为您有充分的理由使用const_cast
,那么您可能真的应该查找mutable
。编辑:我想我应该立即说出来,但是 C 风格的强制转换可以转换为无法访问的基类。例如,考虑如下内容:
[编辑:我正在将代码更新为可以编译并(通常)演示问题的内容。 ]
使用
reinterpret_cast
的代码将编译——但是尝试使用结果(至少两者之一)将导致一个主要问题。reinterpret_cast
获取派生对象的基地址,并尝试将其视为指定类型的基对象 - 并且因为(最多)一个基对象实际上可以存在于该地址,尝试将其视为其他地址可能/将导致重大问题。编辑:在这种情况下,除了打印的内容之外,这些类本质上是相同的,因此尽管任何事情都可能发生,但对于大多数编译器来说,最后两个都会打印出“base 1”。 reinterpret_cast 接受该地址处发生的任何内容,并尝试将其用作指定的类型。在这种情况下,我(试图)让它做一些无害但可见的事情。在实际代码中,结果可能不会那么漂亮。如果代码使用公共继承而不是私有继承,C 风格的强制转换将像 static_cast 一样工作——即它知道派生类中每个基类对象“存在”的位置,并调整结果,因此每个结果指针将工作,因为它已被调整为指向正确的位置。
No. A C cast can do the equivalent of a
const_cast
, astatic_cast
, areinterpret_cast
, or a combination thereof. In case that wasn't quite enough, it can also do at least one minor trick that no combination of the newer casts can do at all!You can use
const_cast
with defined results if the original variable is defined withoutconst
, but all you have is aconst
pointer or reference to that object. OTOH, if you think you have a good reason to use aconst_cast
, chances are that you should really look upmutable
instead.Edit: I suppose I should have said it right off, but a C-style cast can convert to an an inaccessible base class. For example, consider something like:
[Edit: I'm updating the code to something that'll compile and (usually) demonstrate problem. ]
The code using the
reinterpret_cast
s will compile -- but attempting to use the result (of at lest one of the two) will cause a major problem. Thereinterpret_cast
takes the base address of the derived object and attempts to treat it as if it was the specified type of base object -- and since (at most) one base object can actually exist at that address, trying to treat it as the other can/will cause major problems. Edit: In this case, the classes are essentially identical except for what they print, so although anything could happen, with most compilers, both of the last two will print out "base 1". The reinterpret_cast takes whatever happens to be at that address and tries to use it as the specified type. In this case, I've (tried to) make that do something harmless but visible. In real code, the result probably won't be so pretty.The C-style cast will work like a static_cast would if the code had used public inheritance instead of private -- i.e. it's aware of where in the derived class each base class object "lives", and adjusts the result, so each resulting pointer will work because it's been adjusted to point at the right place.
不,C 风格的转换可以根据情况充当
reinterpret_cast
、const-cast
或static_cast
。这就是他们灰心丧气的原因——您在代码中看到 C 风格的转换,需要查找详细信息以了解它会做什么。例如:No, C-style casts can act as
reinterpret_cast
s,const-cast
s orstatic_cast
s depending on the situation. This is why they are discouraged - you see a C-style cast in code and need to look for details to see what it will do. For example:请记住,const 强制转换可能会作用于原始标识符以外的其他内容:
因此,虽然 doit 强制转换为 const,但在此示例中,底层字符串不是 const,因此没有未定义的行为。
更新
好的,这是一个更好的例子,说明使用 const_cast 并非完全没有价值。我们从带有一个带有 const 参数的虚函数的基类开始:
现在您想要重写该虚函数。
由于代码的逻辑/结构,您知道
child::doit
只会使用非常量字符串调用(并且class base
不在您的控制之下,因此您无法修改它,也无法更改child::doit
的签名,因为这样它将不再覆盖base::doit
)。在这种情况下,丢弃 const 是安全的。是的,这是有风险的。也许当你这样写的时候,执行确实永远不会到达带有非常量字符串的
child::doit
并且代码是有效的。但是,在维护您的程序时,或者在您重建并获取最新版本的类库
时,这种情况可能会发生变化。Remember, that a const cast may be acting on something other then the original identifier:
So while doit is casting away const, in this example the underlying string is not const so no undefined behavior.
Update
Okay, here's a better example of when using const_cast is not completely worthless. We start with a base class with a virtual function that takes a const parameter:
and now you want to override that virtual function.
Because of the logic/structure of your code, you know that
child::doit
will only be called with non-const strings (andclass base
is not under your control so you can't modify it nor can you change the signature ofchild::doit
because then it will not longer overridebase::doit
). In this case, it's safe to cast away const.Yes, this is risky. Perhaps when you write that, it's true that the execution will never reach
child::doit
with a non-const string and the code is valid. But that could change either while maintaining your program or perhaps when you rebuild and pick up the latest version ofclass base
.const_cast
用于从类型中删除const
。它还可以删除易失性
。如果对象确实是 const,则结果无法写入,但仍然是明确定义的行为。但是,如果将其提升为const
(通过传递到const T
函数),则将其const_cast
返回为非>const
可以。(我在此处找到了更多信息)reinterpret_cast
无法从类型中删除const
或volatile
。 com/questions/332030/when-should-staticcast-dynamiccast-and-reinterpretcast-be-used">另请参阅
const_cast
is used to removeconst
from a type. It also can removevolatile
. If the object really isconst
then the result cannot be written to and still be well-defined behavior. If, however, it is promoted toconst
(by being passed into aconst T
function, thenconst_cast
ing it back to non-const
is ok. ( i found some more info here)reinterpret_cast
cannot removeconst
orvolatile
from a type.see also
C 风格的强制转换实际上是编程的大锤——你基本上告诉编译器,无论如何,那边的方钉都会穿过这个圆孔。从这个意义上说,reinterpret_cast 非常相似。
我认为使用 C++ 风格的强制转换运算符的主要优点是,它们允许您更好地表达您的意图,并允许编译器仍然对您要求其执行的操作进行一些检查,而不是一刀切地检查-全C风格演员阵容。
关于 const_cast - 您经常会遇到通过 const 引用传递对象的情况,仅仅是因为 API 要求您这样做。假设您有一个处理 C 风格字符串的函数 X:
在该函数内,您将参数传递给需要
char *
的 C 函数,即使它没有更改字符串。适应这种情况的唯一方法是const_cast
str.我会非常小心地使用任何类型的转换,通常这表明您的设计有些不太正确,但有时您必须说服编译器它正在查看的挂钩并不像它假设的那样方形。只有这样你才应该使用强制转换运算符。
C-style casts are really the sledge hammer of programming - you basically tell the compiler that the square peg over there will fit through this round hole no matter what. In that sense,
reinterpret_cast
is very similar.The main advantage I see in using the C++-style cast operators are that they allow you to express your intent better and allow the compiler to still to some checking on the operation you're asking it to perform rather than the one-size-fits-all style C cast.
Regarding
const_cast
- you often get into the situation where you are passing an object around via const reference simply because the API requires you to do this. Say, you've got function X that tasks a C-style string:Inside that function you're passing the parameter to a C function that expects a
char *
, even though it's not changing the string. The only way to accommodate this would be toconst_cast
str.I'd be very careful using any sort of cast, often this shows that there is something not quite right with your design but sometimes you have to convince the compiler that the peg it's looking at isn't as square as it assumes. Only then should you use the cast operators.