以下便携式和符合标准的C ++是否始终返回“成功”?
#include <iostream>
#include <cstddef>
struct Containing {
struct {
Containing * get_containing () {
return reinterpret_cast<Containing *> (
(char *) this - offsetof (Containing, inner)
);
}
} inner;
};
int main () {
Containing c;
std::cout
<< (c.inner.get_containing () == &c ? "success" : "fail")
<< std::endl;
}
答案 0 :(得分:3)
#include <iostream>
#include <cstddef>
struct Containing {
struct {
Containing * get_containing () {
return reinterpret_cast<Containing *> (
(char *) this - offsetof (Containing, inner)
);
}
} inner;
};
int main () {
Containing c;
std::cout
<< (c.inner.get_containing () == &c ? "success" : "fail")
<< std::endl;
}
您显示的具体代码(我在上面重复过)是正常的,因为支持C兼容性的reinterpret_cast
来自POD的第一个元素。
我记得C ++ 11扩展了reinterpret_cast
工作的类型集。
但是,只要您引入虚拟功能或其他非POD'y内容,就会超出offsetof
的运行状态,以及保证reinterpret_cast
的运行状态。
<强> Standardese 即可。通过在我的PDF阅读器中使用“查找”功能,应用于文档[N3290.pdf](C ++ 11的最终草案,与标准相同),在三次鼠标中单击以下有关offsetof
的信息提供了:
C ++11§18.2/ 4:
“宏offsetof
(类型,成员 - 指示符)在此国际/地区接受一组受限制的类型参数 标准。如果 type 不是标准布局类(第9条),则结果是未定义的。“
同样,通过点击标题9中关于“类”的标题,然后要求PDF阅读器搜索reinterpret_cast
,我发现......
C ++ 11 9.2 / 20:
“指向标准布局结构对象的指针,适当地使用reinterpret_cast
转换,指向它 初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然“
<强>在实践即可。使用offsetof
作为第一个成员是没有意义的,因为它保证在偏移量0(之前没有填充)。为了使这个东西有意义,你必须指代给定代码的一些逻辑推广,其中......
char
)完成指针运算。然后对于POD类型或C ++ 11更通用的标准布局,offsetof
很好,但reinterpret_cast
需要特定的编译器支持。使用Visual C ++,没关系。使用g ++,如果可能的话,你可以更好地关闭它的愚蠢警告和相关的愚蠢优化,或绕过void
指针。
执行offsetof
的限制通常不是一个好主意。例如。对于虚拟继承,偏移量可以变化很大,而不能仅从静态类型信息中推断出来。