考虑下面的代码 (和事实VirtualAlloc()
返回void*
):
BYTE* pbNext = reinterpret_cast<BYTE*>(
VirtualAlloc(NULL, cbAlloc, MEM_COMMIT, PAGE_READWRITE));
为什么reinterpret_cast
选择,而不是static_cast
?
我曾经认为reinterpret_cast
是如铸造指针确定,并从整数类型(例如像DWORD_PTR
),但是从投void*
到BYTE*
,不是static_cast
OK?
有没有在这个特殊的情况下,任何(细微的?)的差异,或者他们只是两个有效的指针类型转换?
请问C ++标准有一个偏爱这种情况下,建议的方式,而不是其他?
对于敞篷指向基本类型的石膏都具有相同的含义; 所以你是正确的, static_cast
是好的。
当一些指针类型之间的转换, 它可能是在指针需要保持特定的内存地址改变 。
这就是两种不同的铸件。 static_cast
会做出相应的调整。 reinterpret_cast
不会。
出于这个原因,这是一个良好的一般规则static_cast
,除非你知道 ,指针类型之间reinterpret_cast
需要。
你应该static_cast
。 使用static_cast
在你解开的隐式转换的情况。
在这种特殊情况下,然而,没有任何区别,因为你是从转换void*
。 但在一般情况下, reinterpret_cast
2个对象指针之间荷兰国际集团被定义为(§5.2.10/ 7):
一个对象指针可以显式转换到二FF erent类型的对象的指针。 当prvalue v
型“指针的T1
”被转换为类型“指向cv T2
”, 结果是static_cast<cv T2*>(static_cast<cv void*>(v))
如果两个T1
和T2
是标准-layout类型和的对准要求T2
并不比那些更严格的T1
,或者如果任一类型是void
。 转换类型的prvalue“指针T1
”的类型“指针T2
”(其中T1
和T2
是对象类型,并且其中的对准要求T2
并不比那些更严格的T1
),并返回到其原始类型产生的原始指针值。 任何其它这样的指针转换的结果是unspeci音响编辑。
重点煤矿。 由于T1
你已经是void*
,要转换成void*
中reinterpret_cast
什么都不做。 这不是一般的真实,这正是德鲁杜曼是说 :
#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
,另一方面保证,如果你从一种类型转换指针到其他,回到原来的类型,地址被保留。
虽然大部分的实现,你会看到在使用这两种相同的结果, static_cast
应该是首选。
并与C++11
我记得,使用reinterpret_cast
为void*
有一个明确的行为。 在此之前,这种行为是被禁止的。
It is not permitted to use reinterpret_cast to convert between pointers to object type and pointers to void.
建议的决议(2010年8月):
改变5.2.10 [expr.reinterpret.cast]段落7如下:
一个对象的指针可以被明确地转换为不同类型的对象的指针。 当型“指针T1”的prvalue v是转换为类型“指向cv T2”,其结果是的static_cast(的static_cast(V))如果两个T1和T2是标准布局类型(3.9 [basic.types] )和T2的对准要求并不比T1的严格,或者如果任一类型是无效的。
转换类型的prvalue“指针T1”的类型“指针T2”(其中,T1和T2是对象类型,并且其中T2的对准要求并不比T1的更严格的),并返回到其原始类型产生的原始指针值。 任何其它这样的指针转换的结果是不确定的。
更多信息这里 。
感谢杰西良好的链接。