以下可移植且符合标准的 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;
}
最佳答案
#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
。
标准语。通过使用我的 PDF 阅读器中的“查找”功能,应用于文档 [N3290.pdf](C++11 的最终草案,与标准相同),单击鼠标三下即可获得有关 offsetof< 的以下信息
被提供:
C++11 §18.2/4:
“The macrooffsetof
(type, member-designator) accepts a restricted set of type arguments in this International Standard. If type is not a standard-layout class (Clause 9), the results are undefined.”
同样,通过单击关于“类”的标题 9,然后让 PDF 阅读器搜索 reinterpret_cast
,我发现......
C++11 9.2/20:
“A pointer to a standard-layout struct object, suitably converted using areinterpret_cast
, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa”
实践中。对第一个成员使用 offsetof
有点没有意义,因为它保证位于偏移量 0(之前没有填充)。为了使这件事有意义,您必须对给定代码进行一些逻辑概括,其中……
- 相关成员不是第一个成员。
- 指针运算是通过指向字节的指针完成的(例如
char
)。
然后对于 POD 类型,或 C++11 更通用的标准布局,offsetof
没问题,但 reinterpret_cast
需要特定的编译器支持。使用 Visual C++ 就可以了。对于 g++,如果可能的话,您最好要么关闭它的愚蠢警告和相关的愚蠢优化,要么绕过 void
指针。
超出 offsetof
的限制通常不是一个好主意。例如。对于虚拟继承,偏移量可以有很大差异,不能仅从静态类型信息中推导出来。
关于c++ - 计算包含对象的this指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20773783/