C++ 标准(引用自 n3242 草案)关于子对象 [intro.object] 的说明如下:
Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two distinct objects that are neither bit-fields nor base class subobjects of zero size shall have distinct addresses.
现在,给定以下片段:
struct empty { };
struct member: empty { };
struct derived: empty { member m; };
int main(void)
{
printf("%d", sizeof(derived));
return 0;
}
我相信 gcc 会打印出 2
,而 Visual C++ 2010 会打印出 1
。我怀疑 gcc 正在采用标准来表示如果类型代表不同的对象,则不能为类型的存储设置别名。我敢打赌 MSVC 正在采用标准来表示如果一个子对象的大小为零,您可以做任何您想做的事。
这是未指明的行为吗?
最佳答案
扩展我之前的评论:
对象由其地址标识。如果您比较两个相同类型的对象的地址(如指针)并且它们比较相等,则指针被认为指向同一个对象。
不同类型的对象不能这样直接比较,所以允许它们有相同的地址。一个示例是结构及其第一个成员。它们不能是同一类型。基类和派生类也不能,因此如果基类为空,它们可能具有相同的地址。
但是,基类和派生类的第一个成员可以是同一类型。这不是问题,除非基类也为空并且编译器尝试空基类优化。在那种情况下,我们可以让指向相同类型的两个不同对象的指针比较相等,因此相信它们是同一个对象。
因此,如果成员具有不同的类型(空和字符),它们可以具有相同的地址。如果它们属于同一类型,则它们不能,因为这会破坏对对象身份的测试,例如 if (this != &that)
,有时用于测试自赋值之类的事情。
顺便说一下,Microsoft 同意这是他们编译器中的一个错误,但还有其他更紧急的事情需要首先修复。
关于c++ - 空基类是否会影响派生类的布局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7760198/