正确的方法来投射指针types

考虑下面的代码 (以及VirtualAlloc()返回一个void* )的事实:

 BYTE* pbNext = reinterpret_cast<BYTE*>( VirtualAlloc(NULL, cbAlloc, MEM_COMMIT, PAGE_READWRITE)); 

为什么selectreinterpret_cast而不是static_cast

我曾经认为reinterpret_cast是好的例如铸造指针和整数types的指针(如DWORD_PTR ),但从一个void*转换为BYTE* ,是不是static_cast好吗?

在这种特殊情况下是否存在任何(微妙的)差异,还是仅仅是有效的指针转换?

C ++标准是否对这种情况有偏好,build议一种方式而不是另一种?

对于指向基本types的指针来说,可以接受cast,所以static_cast没问题。

在两种指针types之间转换时,指针中保存的特定存储器地址可能需要更改

这是两个演员不同的地方。 static_cast会做适当的调整。 reinterpret_cast将避免改变指针的存储值。

出于这个原因,除非你知道 reinterpret_cast是需要的,否则在指针types之间static_cast是一个很好的通用规则。

你应该static_cast如果您要撤消隐式转换,请使用static_cast

然而,在这种特殊情况下,没有什么区别,因为你是从void*转换而来的。 但通常,两个对象指针之间的reinterpret_cast定义为(§5.2.10/ 7):

一个对象指针可以被明确地转换为一个不同types的对象指针。 如果T1T2都是标准的,当“指向T1指针”types的prvalue v被转换为types“指向cv T2指针”时, 结果是static_cast<cv T2*>(static_cast<cv void*>(v)) T2的布局types和alignment要求并不比T1更严格,或者任何一种types都是void 。 将“指向T1指针”types的prvalue转换为types“指向T2指针”(其中T1T2是对象types, T2的alignment要求不比T1的alignment要求更严格)并返回到原始types,指针值。 任何其他这种指针转换的结果都是未知的。

强调我的。 因为你的T1已经是void* ,所以在reinterpret_castvoid*什么也不做。 总的来说,这是不正确的, Drew Dormann说的是 :

 #include <iostream> template <typename T> void print_pointer(const volatile T* ptr) { // this is needed by oversight in the standard std::cout << static_cast<void*>(const_cast<T*>(ptr)) << std::endl; } struct base_a {}; struct base_b {}; struct derived : base_a, base_b {}; int main() { derived d; base_b* b = &d; // implicit cast // undo implicit cast with static_cast derived* x = static_cast<derived*>(b); // reinterpret the value with reinterpret_cast derived* y = reinterpret_cast<derived*>(b); print_pointer(&d); print_pointer(x); print_pointer(y); } 

输出:

00CBFD5B
00CBFD5B
00CBFD5C

(请注意,因为y实际上并不指向derived ,所以使用它是未定义的行为。)

在这里, reinterpret_cast出现了一个不同的值,因为它经历了void* 。 这就是为什么你应该尽可能使用static_cast ,而在必要的时候应该使用reinterpret_cast

使用static_cast来指向和从void*指针保证保存地址。

reinterpret_cast另一方面保证,如果您将指针从一种types转换为其他types,并返回到原始types,地址将被保留。

尽pipe在大多数实现中,使用其中任何一个都会看到相同的结果,但static_cast应该是首选的。

而我用C++11记得,使用reinterpret_cast for void*具有定义良好的行为。 在此之前,这种行为被禁止。

 It is not permitted to use reinterpret_cast to convert between pointers to object type and pointers to void. 

build议的决议案(2010年8月):

更改5.2.10 [expr.reinterpret.cast]第7段如下:

对象指针可以显式转换为不同types的对象指针。 如果T1和T2都是标准布局types(3.9 [basic.types] ),则将“指向T1的指针”的prvalue v转换为types“指向cv T2的指针”,结果为static_cast(static_cast(v) ),并且T2的alignment要求不比T1更严格,或者任何一种types都是无效的。

将“指向T1的指针”types的prvalue转换为types“指向T2的指针”(其中T1和T2是对象types,T2的alignment要求不比T1的alignment要求更严格)并返回到原始types,指针值。 任何其他这样的指针转换的结果是未指定的。

更多信息在这里 。

感谢Jesse Good提供的链接。