在什么情况下,应该使用双链式static_cast而不是reinterpret_cast ?

C++ When should we prefer to use a two chained static_cast over reinterpret_cast

本文关键字:cast static reinterpret 情况下 在什么      更新时间:2023-10-16

首先,这不是c++中为什么两个链接的static_cast可以完成它的工作时,我们有reinterpret_cast的副本。

我知道在某些情况下,我们甚至不能使用两个链static_cast来实现reinterpret_cast的作用。但是,是否有任何情况下,我应该更喜欢两个链接的static_cast,而不是一个简单的和更可读的reinterpret_cast ?

reinterpret_cast应该是一个巨大的闪烁符号,表示这看起来很疯狂,但我知道我在做什么。不要因为懒惰而使用它。

reinterpret_cast表示"将这些位视为…"链式静态强制转换不同,因为它们可以根据继承格修改目标。

struct A {
    int x;
};
struct B {
    int y;
};
struct C : A, B {
    int z;
};
C c;
A * a = &c;
int main () {
    assert (reinterpret_cast <B *> (a) != static_cast <B *> (static_cast <C *> (a)));
}

如果您不能100%确定a指向b,则使用dynamic_cast,它将搜索上述解决方案(尽管有运行时成本)。请记住,这可能会在失败时返回NULL或抛出。

我试着想想我实际使用reinterpret_cast的时间,实际上只有两个:

  • 当一个函数压缩/加密任意缓冲区,我想使用const char *来遍历它
  • if(*reinterpret_cast<uint32_t*>(array_of_4_bytes_A) < *reinterpret_cast<uint32_t*>(array_of_4_bytes_B)之类的。像这样的台词会引起仔细审查并要求评论。

如果你的A*实际上是B*,那么你可能需要一个并集

我宁愿看到reinterpret_cast <TargetType> (pointer_of_some_other_type)而不是static_cast <TargetType> (static_cast <void*> (pointer_of_some_other_type))static_cast <TargetType> ((void*) (pointer_of_some_other_type))。通过void*的强制转换链只是一种狡猾的、不正当的方式,以避免使用可怕的reinterpret_cast。

许多项目禁止使用reinterpret_cast,除非获得豁免;编写代码的人需要证明强制转换的使用是正确的。在我看来,静态强制转换链比reinterpret_cast更差(差得多!)该链具有与reinterpret_cast相同的效果和相同的问题,但是该链不具有易于使用grep查找的优点。

附录
这样看。情况1,你使用reinterpret_cast,你通过所有的项目流程来证明它的使用是合理的,项目经理同意放弃。几个月后,一个错误被追踪到您使用了dynamic_cast。你有一张免坐牢卡。给你那张卡片是项目经理的责任。

用例2,您使用了偷偷摸摸的静态类型转换链,代码会安然无恙地通过同行评审。几个月后,一个错误被追查到你使用了卑鄙的技术。你的项目经理可能会因为没有发现这些肮脏的东西而遇到一点麻烦,但这是你的屁股。你没有那张免坐牢卡。你没有通过围棋。你直接去找失业救济

总是把重新解释强制转换作为最后的手段——它不做任何检查!-所以如果你能把两个,三个或十个语句链接在一起,对操作进行某种形式的验证,那么你就获得了一些有价值的东西。

由于场景列表可能很长,所以我用简单的话来表示:

如果链接的static_cast<>不会产生编译错误,那么应该避免使用reinterpret_cast<>

你不应该在交叉转换指针的情况下使用reinterpret_cast -而是使用隐式转换到void*,然后static_cast

因为从理论上讲,它们可以做一些不同的事情(尽管很难想象这种情况)。更重要的是,它们向读者发送不同的信号,并向编译器讲述不同的故事(这可能会影响优化)。从逻辑上讲,我会说使用链式static_castvoid*的情况下,从一个字符类型(例如转储原始内存的图像),和其他情况下,定义良好,可移植,和reinterpret_cast当你做真正的低层次,硬件依赖的工作:提取float的指数字段通过将其地址转换为unsigned int*,和位掩码,例如。