正确的投射指针类型的方法

Mr.*_*C64 47 c++ pointers casting static-cast reinterpret-cast

考虑以下代码(以及VirtualAlloc()返回avoid*的事实):

BYTE* pbNext = reinterpret_cast<BYTE*>(
    VirtualAlloc(NULL, cbAlloc, MEM_COMMIT, PAGE_READWRITE));
Run Code Online (Sandbox Code Playgroud)

为什么reinterpret_cast选择而不是static_cast

我以前认为reinterpret_cast可以用于例如从整数类型(例如DWORD_PTR)转换指针,但是从a转换void*为a BYTE*,是不是static_cast可以?

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

C++标准是否偏爱这种情况,建议采用一种方式而不是另一种方式?

Dre*_*ann 39

对于基本类型的可转换指针,两个转换具有相同的含义; 所以你是对的,static_cast没关系.

在某些指针类型之间进行转换时,指针中保存的特定内存地址可能需要更改.

这就是两个演员的不同之处. static_cast会做出适当的调整. reinterpret_cast将不会.

因此,static_cast除非您知道需要,否则指针类型之间的一般规则是很好的reinterpret_cast.


GMa*_*ckG 23

你应该static_cast.用于static_cast撤消隐式转换的情况.

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

可以将对象指针显式转换为不同类型的对象指针.当prvalue v类型的"指针T1"被转换为类型"指向cv T2",其结果是static_cast<cv T2*>(static_cast<cv void*>(v)),如果这两个T1T2是标准布局类型和的对准要求T2并不比那些更严格的T1,或者如果任一类型是void.将"指向T1"的类型的prvalue转换为"指向"的类型T2(其中T1T2是对象类型,并且对齐要求T2不比那些更严格T1)并返回其原始类型,产生原始指针值.任何其他此类指针转换的结果都是未指定的.

强调我的.既然T1你已经是void*,中投以void*reinterpret_cast不执行任何操作.总的来说这不是真的,这就是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);
}
Run Code Online (Sandbox Code Playgroud)

输出:

00CBFD5B
00CBFD5B
00CBFD5C

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

在这里,reinterpret_cast提出了一个不同的价值,因为它经历了void*.这就是为什么你应该尽可能使用static_cast,reinterpret_cast何时必须使用.


Tux*_*ude 8

static_cast一个指针转换为和void*保证保留地址.

reinterpret_cast 另一方面,保证如果将指针从一种类型转换为另一种类型,并返回原始类型,则保留地址.

虽然对于大多数实现,您会看到使用其中任何一个的相同结果,static_cast应该是首选.

而且C++11我记得,使用reinterpret_castfor void*有一个明确定义的行为.在此之前,此行为被禁止.

It is not permitted to use reinterpret_cast to convert between pointers to object type and pointers to void.
Run Code Online (Sandbox Code Playgroud)

拟议决议(2010年8月):

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

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

将"指向T1的指针"类型的prvalue转换为"指向T2的指针"类型(其中T1和T2是对象类型,T2的对齐要求不比T1更严格)并返回其原始类型会产生原始类型指针值.未指定任何其他此类指针转换的结果.

更多信息在这里.

感谢Jesse Good提供的链接.

  • 这是关于重新解释演员的[链接](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1120),它实际上是在C++ 11之前被禁止的. (2认同)