根据 C++ 标准,指针
reinterpret_cast
到其他类型指针 T*
可以更改或不更改指针值,具体取决于实现。 我非常感兴趣 - 是否有任何 C++ 实现的真实示例,其中使用
Q*
将指针转换为其他指针类型会更改指针?那里发生了什么变化以及为什么变化?
我能想到的最接近的是硬件需要类型对齐的架构,以及决定在需要时纠正对齐的实现。比如:
reinterpret_cast
可能要求
aligned8 var;
aligned1 *p = reinterpret_cast<aligned1*>(&var);
aligned1 *q = p + 1; // assuming aligned 1 size is not multiple of 8
aligned8 *a = reinterpret_cast<aligned8*>(q); // [1]
成为有效指针,它必须寻址 8 倍数的内存位置,而具有较少对齐要求的参数
a
可以指向任何内存地址。class A1 { int a1; };
class A2 { int a2; };
class B: public A1, public A2 { };
#define DBG(val) cout << #val << ": " << val << endl
// test code
B b;
DBG(&b); // prints 0x42
void *p_blank = &b;
DBG(p_blank); // prints 0x42
A2 *p_a2 = &b;
DBG(p_a2); // prints 0x46
void *p_reinterpreted = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted); // prints 0x42
A2 *p_reinterpreted2 = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted2); // prints 0x42
的意思是
给我指向B对象中的A2对象的指针。
A2 *p_a2 = &b
的意思是给我指向b的指针并将其视为A2指针。 这个reinterpret_cast的结果具有“指向A2的指针”类型,因此当分配给void *变量(或A2 *变量)时它不会产生警告。
最可能的影响是截断,因为目标指针类型缺少指定索引部分的位。 C++11 在这个方向上给予了认可,只要任何指针类型具有相同的对齐要求,它们就可以被
reinterpret_cast<A2*>(&b)
ed。通过严格对齐“归零”的位不允许存在。
对象指针可以显式转换为以下对象指针 不同的类型。当“指向 T1 的指针”类型的纯右值 v 为 转换为“指向 cv T2 的指针”类型,如果 T1 和 T2 都是标准布局,则结果为
reinterpret_cast
类型 (3.9)
并且 T2 的对齐要求不比 T1,的那些或如果任一类型无效。转换类型的纯右值 “指向 T1 的指针”到“指向 T2 的指针”类型(其中 T1 和 T2 是 对象类型并且没有 T2 的对齐要求 比 T1 更严格)并返回其原始类型,得出 原始指针值。任何其他此类指针的结果 转换未指定。
在多重继承的情况下,就像 David Rodriguez 所说的那样,获取一个基址的地址可能会返回一个与第一个基址的地址有偏移量的地址。 Reinterpret_cast 将返回该偏移地址,但如果您将其视为向上转换地址,则会发生地狱。
对于向上转换,static_cast 可以返回与给定地址不同的地址。如果您拥有的地址是其中一个基地址,并且该地址位于第一个基地址的偏移量处,则 static_cast 将为向上转换的对象返回一个有效地址,该地址等于第一个基地址的地址,因此不等于到传递的指针。
简而言之:reinterpret_cast 始终为您提供相同的地址。 static_cast 和dynamic_cast 可能返回不同的地址,例如在某些涉及多重继承的情况下。
static_cast 和dynamic_cast 之间的区别在于,static_cast 不会检查您给它的指针是否是用于强制转换的正确对象,因此在调用它之前请确保这一点。