可能重复:
Should I use static_cast or reinterpret_cast when casting a void* to whatever
通常,特别是在Win32编程中,需要从一个opaque类型转换为另一个opaque类型。例如:
HFONT font = cast_here<HFONT>( ::GetStockObject( SYSTEM_FONT ) );
static_cast和reinterpret_cast在这里都适用,并且具有完全相同的效果,因为HFONT是一个指向伪结构的指针,该结构专门用于定义由GetStockObject()返回的HFONT和HGDIOBJ是一个void *指针。
哪一个 - static_cast或reinterpret_cast - 更好?
答案 0 :(得分:15)
说明演员表具有相同的效果是不正确的。演员表演两件完全不同的事情:
static_cast<T>(x)
表示将表达式x
转换为T
类型。reinterpret_cast<T*>(&x)
表示将内存位置'&amp; x'解释为T * 请考虑以下事项:
struct A1 { int a1; };
struct A2 { int a2; };
struct B : public A1, public A2 {};
void foo (A1 * a1, A2 * a2)
{
B * b1_a1 = static_cast<B*> (a1);
B * b2_a1 = reinterpret_cast<B*> (a1);
B * b1_a2 = static_cast<B*> (a2);
B * b2_a2 = reinterpret_cast<B*> (a2);
std::cout << "b1_a1==b1_a2" << (b1_a1==b1_a2) << std::endl;
std::cout << "b2_a1==b2_a2" << (b2_a1==b2_a2) << std::endl;
}
int main ()
{
B b;
foo (&b, &b);
}
此程序产生以下输出:
g++ -o t t.cc ; ./t
b1_a1==b1_a2: 1
b2_a1==b2_a2: 0
这显示static_cast
从a2
到b2
如何正确调整指针,使其指向b
的开头,但reinterpret_cast
执行了{{1}}不
答案 1 :(得分:12)
static_cast
总是更可取,除非绝对必要,否则请避免reinterpret_cast
。
reinterpret_cast
是最不安全的演员阵容。
this website关于在何时使用哪些演员表的更多信息。
答案 2 :(得分:4)
由于reinterpret_cast是实现定义的,我的经验法则是:“static_cast我可以,reinterpret_cast我必须”。
(其他演员除外)
答案 3 :(得分:2)
static_cast是首选。
来自Scott Meyers的更有效的C ++
此运算符[reinterpret_cast]用于执行类型 结果差不多的转换 总是实现定义的。作为一个 结果,reinterpret_casts很少 便携式的。
reinterpret_cast的最常见用法是在函数指针类型之间进行转换。
答案 4 :(得分:2)
我认为static_cast会更好。这里的another stack overflow post也有更多关于此的讨论。
答案 5 :(得分:2)
每个人都注意到reinterpret_cast&lt;&gt;比static_cast&lt;&gt;更危险 这是因为reinterpret_cast&lt;&gt;忽略所有类型信息,只是分配一个没有任何实际处理的新类型,因此完成的处理是实现定义的(尽管通常指针的位模式是相同的)。
每个人都没提到的是reinterpret_cast&lt;&gt;是一种记录您的程序的方法。它告诉有人阅读我们必须妥协的代码,因此我们最终会遇到危险的演员,并且当你搞乱这段代码时要小心。
使用reinterpret_cast&lt;&gt;在代码中突出显示这些危险区域。
从无效*中进行投射时,没有要使用的强制转换的类型信息 因此,您要么进行无效的强制转换,要么转换回原先转换为void *的原始类型。任何其他类型的强制转换都会导致一些未定义的行为。
这是使用reinterpret_cast&lt;&gt;的完美情况因为标准保证使用reinterpret_cast&lt;&gt;转换指向void *并返回其原始类型的指针将工作。并通过使用reinterpret_cast&lt;&gt;你指的是后来出现的人类,这里发生了一些不好的事情。
答案 6 :(得分:1)
你应该真的做任何win32文档所说的正确的事情。这是最有可能工作的,最有可能是前向兼容的,除非我的作者完全无能为力。
更新:我查了一下。 Win32文档使用C样式转换。在这种情况下,C ++定义了一个C样式转换来执行static cast
。所以正确的答案是:使用static_cast
。或者是C风格演员,但他们通常最好避免使用。
答案 7 :(得分:0)
我的正常建议:
reinterpret_cast<>
仅用作最后的手段。你告诉编译器要抛弃所有的注意事项,“删除所有的安全设备”,并且相信你的话,它确实是好的,无论编译器知道什么代码。只有在没有别的办法可以使用时才应该使用它。
有些地方可能会产生相同的效果 IF 您的代码是正确的。如果你最终做出更改并引入错误并且演员阵容不再正确,static_cast<>
可能会抓住它,但reinterpret_cast<>
肯定不会。
在这个非常特殊的场景中,最后一个参数并没有那么多:API正在强加你的语义;他们的语义很好理解;你正在施放(无效*)。
不过,我会使用static_cast<>
,并将reinterpret_cast<>
留给真正非凡环境迫使我绕过类型安全的地方。由于API的C兼容性,这是一个“正常”强制转换。
(有关static_cast&lt;&gt;和reinterpret_cast&lt;&gt;)
之间差异的更多详细信息,另请参阅my post here