我应该使用它还是static_cast <void *> then static_cast <mytype *>以避免reinterpret_cast?</mytype *> </void *>

时间:2014-02-05 09:49:05

标签: c++ casting reinterpret-cast static-cast

我见过人们建议使用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 但回想一下我的问题来自于无关紧要。

2 个答案:

答案 0 :(得分:7)

§5.2.10描述了reinterpret_cast可以执行的合法映射,并指定“不能执行其他转换”。

与您的示例相关的转换为/ 7:

  

指向对象的指针可以显式转换为指向不同对象类型的指针。当“指向v的指针”的prvalue T1转换为“指向 cv T2的指针”时,结果为static_cast<cv T2*>(static_cast<cv void*>(v)) 如果T1T2都是标准布局类型...... 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 ++中进行强制转换的规则是:

  1. 使用C ++样式强制转换xx_cast<T*>而非C样式(T*),因为 explicit比隐式更好。
  2. 只有当你真正的意思时才使用重新解释。
  3. 如果您使用reinterpret_cast<T*>,请确保投射/取消投射是精确的镜像,例如:
  4. T* obj = ...;
    void* tmp = reinterpret_cast<void*> obj;
    T* ref = reinterpret_cast<T*> tmp;  // T* obj --> T* ref
    

    在这里,你必须确保objref是完全相同的类型,包括const限定符,类派生,对齐,内存类型(嵌入式),绝对是你能想到的任何东西。< / p>