根据严格的别名规则:
struct B { virtual ~B() {} };
struct D : public B { };
D d;
char *c = reinterpret_cast<char*>(&d);
char*
对任何不同类型的对象都有效。但现在的问题是,它是否会指向&amp; d的相同地址? C ++标准保证它将返回相同的地址是什么?
答案 0 :(得分:6)
c
和&d
确实具有相同的值,如果您将c
重新解释为D*
,则会得到一个有效的指针,您可以取消引用它。此外,您可以将c
视为(指向第一个元素的指针)不透明数组char[sizeof(D)]
- 这确实是将指针转换为指针的主要目的:允许(反)序列化(例如ofile.write(c, sizeof(D));
),尽管通常只应对原始类型(及其数组)执行此操作,因为复合类型的二进制布局通常不以便携方式指定。
正如@Oli正确地指出并希望我强化一样,你应该永远不要将复合类型作为一个整体来序列化。结果几乎永远不会反序列化,因为数据字段之间的多态类和填充的实现没有指定,也无法访问。
请注意,reinterpret_cast<char*>(static_cast<B*>(&d))
可以通过类似的推理视为不透明数组char[sizeof(B)]
。
答案 1 :(得分:2)
2003年C ++标准第5.2.10节第7点说:
指向对象的指针可以显式转换为指向的指针 不同类型的对象。除了转换类型的右值 “指向T1的指针”到“指向T2的指针”(其中T1和T2为 对象类型以及T2的对齐要求为否 比T1更严格,回到原来的类型产生了 原始指针值,这种指针转换的结果是 未指定的。
如果“同一地址”表示“原始指针值”,则此条目显示“是”。
答案 2 :(得分:0)
意图很明确(而不是需要辩论的事情):
reinterpret_cast
永远不会更改地址的值,除非目标类型无法表示所有地址值(如小型整数类型,具有内部对齐的指针类型:f.ex 。一个只能表示偶数地址的指针,或者指向对象的指针和指向函数的指针不能混合......)。
该标准的措辞无法捕捉到这一点,但这并不意味着这里存在真正的实际问题。
char *c = reinterpret_cast<char*>(&d);
c
将始终指向d
的第一个字节。