我见过人们建议使用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 here http://blogs.msdn.com/b/vcblog/archive/2014/02/04/challenge-vulnerable-code.aspx 但回想一下我的问题来自于无关紧要。
答案 0 :(得分:7)
§5.2.10描述了reinterpret_cast
可以执行的合法映射,并指定“不能执行其他转换”。
与您的示例相关的转换为/ 7:
指向对象的指针可以显式转换为指向不同对象类型的指针。当“指向
v
的指针”的prvalueT1
转换为“指向 cvT2
的指针”时,结果为static_cast<cv T2*>(static_cast<cv void*>(v))
如果T1
和T2
都是标准布局类型......T2
的对齐要求不比T1
更严格。 [强调我的]
任何其他指针转换为对象类型的结果都是“未指定”。 1
这是reinterpret_cast
危险的两个原因之一:它的转换仅为指向对象类型的指针子集定义良好,编译器通常提供 no 关于意外误用的诊断
第二个原因是编译器甚至不检查您尝试执行的映射是否合法,以及将执行多个(语义上完全不同的)映射中的哪一个。
最好明确并告诉编译器(和读者) 您想要执行的转换。也就是说,asdf的评论不太正确,因为您可能希望通过reinterpret_cast
执行的所有转换相当于使用static_cast<void*>
后跟static_cast
到目标类型。
1 旁白:简而言之(略微简化),“standard layout type”是一种类型(或类型数组),它没有虚函数或混合成员可见性,其所有成员和基地也是标准布局。类型的alignment是对内存中可能位于的地址的限制。例如,许多机器要求double
在可被8整除的地址处对齐。
答案 1 :(得分:2)
asdf
解释得非常好,即使在链接帖子中简明扼要。
因为编译器不知道CustomImage派生自Image at 这一点在该计划中。
就个人而言,我无法从msdn下载垃圾,只是为了深入挖掘并回答问题。毕竟这是一个编码挑战,你应该想出来。
我在C ++中进行强制转换的规则是:
xx_cast<T*>
而非C样式(T*)
,因为 explicit比隐式更好。 reinterpret_cast<T*>
,请确保投射/取消投射是精确的镜像,例如:
T* obj = ...;
void* tmp = reinterpret_cast<void*> obj;
T* ref = reinterpret_cast<T*> tmp; // T* obj --> T* ref
在这里,你必须确保obj
和ref
是完全相同的类型,包括const限定符,类派生,对齐,内存类型(嵌入式),绝对是你能想到的任何东西。< / p>