关于c ++:在将void *转换为任何内容时,我应该使用static_cast还是reinterpret_cast

Should I use static_cast or reinterpret_cast when casting a void* to whatever

静态类型转换和重新解释类型转换对于将void*转换为另一个指针类型似乎都很好。有没有充分的理由让一个胜于另一个?


使用static_cast:它是最窄的强制转换,精确描述了在这里进行的转换。

有一种误解认为,使用reinterpret_cast将是更好的匹配,因为它意味着"完全忽略类型安全性,只从A到B转换"。

然而,这并不能真正描述reinterpret_cast的效果。相反,reinterpret_cast有许多含义,因为所有这些都认为"reinterpret_cast执行的映射是实现定义的。"[5.2.10.3]

但在从void*T*的转换的特殊情况下,标准完全定义了映射;即,在不更改地址的情况下,将类型分配给无类型指针。

这是选择static_cast的原因。

此外,还有一个更重要的事实,即每一次使用reinterpret_cast都是非常危险的,因为它将任何东西转换成其他东西(对于指针),而static_cast的限制性要大得多,因此提供了更好的保护级别。这已经把我从错误中救了出来,我不小心试图将一种指针类型强制转换为另一种类型。


这是一个棘手的问题。一方面,Konrad对Reinterpret-Cast的规范定义提出了一个很好的观点,尽管在实践中它可能也做了同样的事情。另一方面,如果在指针类型之间进行强制转换(例如,通过char*在内存中进行索引时,这种情况很常见),静态的u强制转换将生成一个编译器错误,并且无论如何都将强制使用reinterpret u强制转换。

在实践中,我使用了reinterpret_cast,因为它更能描述cast操作的意图。当然,您可以使用不同的运算符来指定指针重新解释(这样可以保证返回的地址相同),但标准中没有。


我建议总是使用最薄弱的演员阵容。

reinterpret_cast可用于向float投射指针。破坏铸件的结构越多,使用它所需的注意力就越多。

char*的情况下,我会使用C样式的cast,直到我们有了一些reinterpret_pointer_cast为止,因为它比较弱,其他的都不够。


我个人的偏好基于这样的代码读写能力:

1
2
3
void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();

1
2
3
4
typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();

它们最终都是一样的,但是静态的"投射"在中间的软件、应用程序环境中似乎更合适,而重新解释的"投射"更像是在较低级别的库imho中看到的。