假设我有一个带有一些成员变量且没有虚函数的基类:
class Base {
int member;
};
和一个从Base
以非虚方式派生的派生类,没有新的成员变量,也没有虚函数:
class Derived : Base {
};
显然sizeof(Derived)
不能小于sizeof(Base)
。
sizeof(Derived)
是否必须等于sizeof(Base)
?
答案 0 :(得分:18)
从5.3.2 [expr.sizeof]
当应用于类时,[{1}}]的结果是该类对象中的字节数,包括在数组中放置该类型对象所需的任何填充。最派生类的大小应大于零(1.8)。
从1.8 [intro.object]
除非它是位字段(9.6),否则最派生的对象应具有非零大小并且应占用一个或多个存储字节。基类子对象可以具有零大小。 POD类型(3.9)的对象应占用连续的存储字节。
并注意:
基类子对象的实际大小可能小于将sizeof应用于子对象的结果,这是由于虚基类和对基类子对象的填充要求不太严格。
将这些放在一起,我认为它告诉你的是你对sizeof
可能告诉你的内容没有任何保证,除了结果大于零。事实上,它似乎并不能保证sizeof
!
答案 1 :(得分:13)
没有这样的要求。
我能想到的语言中唯一相关的部分是每个对象,无论是否完整,以及是否有大多数派生,都有身份,它由一对地址和类型给出。参看C ++ 11 1.8 / 6:
如果一个是子对象,则不是位字段的两个对象可以具有相同的地址 另一个,或者如果至少有一个是零大小的基类子对象,它们是不同类型的;否则,他们应有不同的地址。
因此,示例中派生最多的对象和基础子对象必须具有不同的标识。
编译器同时为Base
和Derived
提供1
的大小肯定是有意义的,但这不是强制性的。如果Base
的大小为1729而Derived
的大小为2875,则可以接受。
答案 2 :(得分:9)
有趣的问题。我有一个例子,带有额外字段的派生类是相同大小和空基类。(这应该是注释但是太大了;请接受其中一个答案,尽管如果它很有趣,欢迎大家投票。)
考虑这个简单的C ++程序:
class A {};
class B : public A {
int m_iInteger;
};
int _tmain(int argc, _TCHAR* argv[])
{
printf("A: %d\r\n", sizeof(A));
printf("B: %d\r\n", sizeof(B));
printf("int: %d\r\n", sizeof(int));
return 0;
}
如果sizeof(int)
为4,您对输出的期望是什么?也许是这样的事情:
A: 0
B: 4
int: 4
我的编译器 - Embarcadero C++ Builder 2010 - 提供输出:
A: 8
B: 8
int: 4
换句话说,在派生类中添加额外字段不会使派生类更大。
对于compatibility option Zero-length empty base class上的帮助文件主题有一些了解原因。
通常类的大小至少为一个字节,即使是类 没有定义任何数据成员。设置此选项时, 编译器忽略内存布局和总数的这个未使用的字节 任何派生类的大小;空基类不占用空间 在派生类中。默认= False
对于此编译器,具有默认编译器设置的类的大小似乎是8个字节,而不是一个,实际上,为此代码示例更改此设置 无效。
您可能还会发现this article on base class sizes and the above optimization有趣。它讨论了为什么类必须具有至少一个字节的大小,优化的作用,以及深入研究成员函数的表示等:
实际上,标准要求物体的大小永远不会 为零;它还要求在派生对象中的数据成员 基类应出现在用户声明的数据成员之前 派生类。但是,基类子对象不被视为a 完整对象。因此,可以删除基类 来自派生对象的子对象,不违反规则。在 换句话说,在对象t中,S和x的偏移可能重叠......
请阅读该文章,了解该报价的完整背景。
答案 3 :(得分:-1)
class Base {
// int member; I have just created an empty base class.
};
class Derived : Base {
};
现在gcc编译器会为Base和Derived类创建的对象提供“size> 0”。 gcc编译器只是为用户提供对象的地址。
Note:Derived class would contain base class members, so obviously we can think of
sizeof(derived class) greater then sizeof(base class). But this depends on the compiler
if it allocates some extra space while defining the derived class.
我现在的gcc编译器显示Base和Derived的sizeof对象相同。