为什么C ++中类的大小取决于数据成员的公共/私有状态?


23

据我所知,C ++中类的大小取决于以下因素:

  1. 所有非静态数据成员的大小。
  2. 数据成员的顺序。
  3. 是否启用字节填充。
  4. 其直接基类的大小。
  5. 虚拟功能的存在。
  6. 继承方式(虚拟继承)。

现在,我创建了两个类,如下所示:

class A{
    int a;
    short s;
    int b;
    char d;
};// kept a char at last on purpose to leave a "hole"

class B : public A{
    char c;  
};

现在检查A和BI的大小,请参见

  • A的大小:16
  • B的大小:16

我的假设是B类中的字符c容纳在A类中剩余的“空洞”中。

但是,令我感到困惑的是以下情况,其中我将成员公开

class A{
    public:
    int a;
    short d;
    int b;
    char s;
};

class B : public A{
    public:
    char c;
};

现在大小变成

  • A的大小:16
  • B的大小:20

我似乎无法理解这种差异的原因。


1
为什么C ++中类的大小取决于数据成员的公共/私有状态?-不是。这些是依赖于编译器的实现细节。
PaulMcKenzie

1
那么,您使用的是什么编译器?
罗曼

2
@PaulMcKenzie确实如此。该标准将具有相同访问权限的成员分组在一起,因此进行更改将更改编译器的填充策略。
NathanOliver

@ NathanOliver-ReinstateMonica,我不知道。您是否有机会参考相关部分?
R Sahu

@RSahu现在抬起头来回答我的问题。
NathanOliver

Answers:


8

Itanium ABI 使用POD的C ++ 03定义来定义“出于布局目的的POD”类。具有私有数据成员会使一个类不能成为聚合类,因此不能成为C ++ 03中的POD:

POD结构是具有式非POD结构,非POD联合(或这种类型的阵列)或参考的没有非静态数据成员的聚合类,并且没有用户定义的复制赋值运算符和无用户定义的析构函数。

成为POD类会禁用尾部填充重用

这些类型的dsize,nvsize和nvalign定义为其普通大小和对齐方式。这些属性仅对用作基类的非空类类型有效。我们忽略POD的尾部填充,因为该标准的早期版本不允许我们将其用于其他任何东西,并且因为它有时允许更快地复制该类型。

因此,在您的第一个示例中,A不是出于布局目的的POD B::c,而是可以将其尾部填充用于,但是在您的第二个示例中,它是POD,并且其尾部填充无法重复使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.