C++ 空类的大小&;派生虚拟类

C++ 空类的大小&;派生虚拟类,c++,class,oop,sizeof,C++,Class,Oop,Sizeof,1.为什么Derived4类的大小显示为8字节 class Empty {}; class Derived4 : virtual public Empty { char c; }; 2.Derived2类的大小显示为4字节 class Empty {}; class Derived2 : virtual public Empty {}; 请注意,sizeof(任意类)是实现定义的 但在你的情况下实际发生了什么。嗯,它使用的是virtual继承,大多数实现都使用隐藏指针来实现此功能,它

1.为什么Derived4类的大小显示为8字节

class Empty
{};
class Derived4 : virtual public Empty
{
    char c;
};
2.Derived2类的大小显示为4字节

class Empty
{};
class Derived2 : virtual public Empty
{};
请注意,
sizeof(任意类)
是实现定义的

但在你的情况下实际发生了什么。嗯,它使用的是
virtual
继承,大多数实现都使用隐藏指针来实现此功能,它需要
sizeof(pointer)
字节(指针存储在派生类本身中),加上所有成员的大小(如果有),加上填充(如果需要),加上基类的大小(在基类为空的情况下,由于空基类优化,可以将其减少为零)

要获得更详细的答案,请在此网站上搜索“C++中的填充”。你会发现很多关于它的话题

为什么
Derived4
类的大小显示8个字节

class Empty
{};
class Derived4 : virtual public Empty
{
    char c;
};
在32位机器下,g++为一个空类生成1字节(以便在内存中表示类名)。这是一种有意的行为

您正在继承
Derived4
中的
Empty
作为
virtual public
,结果是编译器默认在类
Derived4
中创建
\u vptr
变量。因此,类
Derived4
将如下所示

class Derived4 {
  void* __vptr; // 4 bytes
  char c; // 4 bytes as 1 char + 3 for structure padding
};
所以上面这个类的大小是8字节,希望你能同意


Derived2
类的大小显示为4字节

class Empty
{};
class Derived2 : virtual public Empty
{};

这里同样的原则适用于空类1字节,并将
Derived4
中的
empty
继承为插入
Derived4
类中的虚拟结果
\uu vptr
变量。所以,
Dervied4
的大小是
sizeof(void*)
;在32位机器中,它只有4字节的大小。

我要添加到Saravanan语句中,空类的大小确实不是0字节,但当用作基类时,由于EBCO(空基类优化),基类的“开销”被删除。

填充到字边界?如果您添加
char
字段会发生什么情况?这是实现定义的,因此很难回答,但为什么您会在意呢?这是我的赌注。vtable会导致额外的4个字节,而检测到的“char”仅为1个字节,最终总共为5个字节。编译器可能在使用8字节值的指令中使其具有8字节的意义。您会注意到,在
Derived4
的布局中有一个类型为
int32\u t(**)(…)
的隐藏指针:正如其他人所说,这是实现定义的。该标准只讨论各种类型的最小大小(例如,char最小为1字节,但原则上可以是任何更大的数字)。顺便说一句,您使用的是什么编译器?即使是在虚拟继承的情况下,Vptr和Vtable也会出现在图片中吗?我认为只有当yiu在您的类bcz中有虚拟函数时,它才会出现在图片中,而这正是您需要Vtable的时候,请clarify@GeekPanther:是的。一个虚拟基地有一个
vptr
。因此,如果您有两个虚拟基类,那么将有两个
vptr
,并相应地计算类的大小。在基类为空的情况下,编译器可能会对此进行优化,因此它可能只有一个,而不是两个。那么在这种情况下,Vtable的内容是什么,就像Vfunction的情况一样,它包含Vfunction的地址,在虚拟继承(没有任何VFunc)的情况下,Vtable的内容是什么??@GeekPartner:我想它应该是空的,但我不确定,因为编译器在每个新版本中都会有很多技巧,在编译器实现方面没有什么是永久的。你的计划不能依赖那些血淋淋的细节。