C++ 标准(引用草案 n3242)对子对象 [intro.object] 有如下规定:
除非对象是位域或零的基类子对象
size,该对象的地址是它的第一个字节的地址
占据。两个不同的对象,既不是位域也不是基数
零大小的类子对象应具有不同的地址。
现在,给出以下代码片段:
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 采用的标准意味着如果一个子对象的大小为零,您可以做任何您想做的事情。
这是未指定的行为吗?
扩展我之前的评论:
对象由其地址来标识。如果比较相同类型的两个对象的地址(如指针)并且它们比较相等,则指针被视为指向同一对象。
不同类型的对象不能通过这种方式直接比较,因此允许它们具有相同的地址。一个例子是结构体及其第一个成员。它们不能是同一类型。基类和派生类也不能,因此如果基类为空,它们可能具有相同的地址。
但是,基类和派生类的第一个成员can属于同一类型。这不是问题,除非基类也是空的并且编译器尝试空基类优化。在这种情况下,我们可以将指向同一类型的两个不同对象的指针比较相等,因此相信它们是同一个对象。
因此,如果成员具有不同的类型(空和字符),它们可以具有相同的地址。如果它们属于同一类型,则不能,因为这会破坏对象身份的测试,例如if (this != &that)
,有时用于测试诸如自我分配之类的事情。
顺便说一句,微软同意这是他们的编译器中的一个错误,但还有其他更紧急的事情需要首先修复。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)