我看到有人建议使用 static_cast<SomeType*>(static_cast<void*>(p))
而不是重新解释类型转换。
我不明白为什么这样更好,谁能解释一下?
为了便于讨论,这里有一个需要 reinterpret_cast 的示例场景:
DWORD lpNumberOfBytes;
ULONG_PTR lpCompletionKey;
LPOVERLAPPED lpOverlapped;
GetQueuedCompletionStatus(myHandle, &lpNumberOfBytes, &lpCompletionKey, &lpOverlapped, 0);
if(lpCompletionKey == myCustomHandlerKey){
auto myObject = reinterpret_cast<MyObject*>(lpOverlapped); //i know this is really a MyObject
}
这是我听到的建议:
auto myObject = static_cast<MyObject*>(static_cast<void*>(lpOverlapped));
编辑: 我最初的问题是 在评论部分“asdf”建议在此处使用 static_cast 而不是 reinterpret_cast http://blogs.msdn.com/b/vcblog/archive/2014/02/04/challenge-vulnerable-code.aspx 但回想起来,我的问题来自那里是无关紧要的。
最佳答案
§5.2.10 描述了 reinterpret_cast
的合法映射可以执行,并指定“不能执行其他转换”。
与您的示例相关的转换是/7:
A pointer to an object can be explicitly converted to a pointer to a different object type. When a prvalue
v
of type “pointer toT1
” is converted to the type “pointer to cvT2
”, the result isstatic_cast<<i>cv T2*>(static_cast<cv</i> void*>(v))
if bothT1
andT2
are standard-layout types … and the alignment requirements ofT2
are no stricter than those ofT1
. [emphasis mine]
将任何其他指针转换为对象类型的结果是“未指定的”。1
这是为什么 reinterpret_cast
的两个原因之一是危险的:它的转换仅针对指向对象类型的指针子集进行了明确定义,并且编译器通常不提供有关意外误用的诊断。
第二个原因是编译器甚至不首先检查您尝试执行的映射是否合法,以及将执行许多(语义上完全不同的)映射中的哪一个。
最好是显式地告诉编译器(和读者)您要执行的预期转换是什么。也就是说,asdf 的评论并不完全正确,因为不是您可能希望通过 reinterpret_cast
执行的所有 转换相当于使用 static_cast<void*>
其次是 static_cast
到目标类型。
1 旁白:简而言之(并稍微简化),一个 “standard layout type”是一个没有虚函数或混合成员可见性的类型(或类型数组),它的所有成员和基类也是标准布局。 alignment类型的限制是对其可能位于内存中的地址的限制。例如,许多机器需要 double
s 在可被 8 整除的地址处对齐。
关于c++ - 我应该使用它还是 static_cast<void*> 然后 static_cast<myType*> 来避免重新解释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21573712/