如何理解fdump-class-hierarchy输出

时间:2013-07-23 18:47:43

标签: c++ class compiler-options

我正在使用fdump-class-hierarchy编译器选项,但我不知道如何理解输出。 “大小”,“对齐”,“基本大小”和“碱基对齐”是什么意思,以及这些是如何计算的?谢谢!

当代码是:

class A
{
public:

private:
    double m_nothing;
    int m_number;
};

输出结果为:

Class A
   size=16 align=8
   base size=16 base align=8
A (0x406c690) 0

但是,如果我稍微改变一下课程:

class A
{
public:

private:
    int m_number;
    double m_nothing;
};

输出将是:

Class A
   size=16 align=8
   base size=12 base align=8
A (0x406c690) 0

1 个答案:

答案 0 :(得分:13)

sizealign是用作完整类型时类的大小和对齐方式。也就是说,如果您创建完整类型为该类型的对象(比如定义该类型的变量,或者使用new类型的对象)。

大小只是它占用的字节数。所以size=16意味着当用作完整类型时,它总是占用16个字节。

对齐可以告诉您对象的放置位置:align=8表示对象的地址必须是8的整数倍。

base sizebase align给出大小和对齐,以防该类用作基类。它们不同的原因是C ++标准允许对象在用作基类时使用较少的填充。

所以让我们专门看一下你的例子(我假设你在第一个案例中int之前确实有double。我也省略了publicprivate,因为在这里它们不会改变任何内容(如果你有公共或私人数据成员,他们可能原则上改变了一些东西,但我不知道是否有任何编译器利用了这一点。我也猜测intdouble的大小和对齐方式(实际上我假设的值是非常常见的选择,并解释了你获得的值)。

所以在第一种情况下(我假设)你有

class A
{
  int m_number;
  double m_nothing;
};

现在int的大小和对齐方式为4,而double的大小和对齐方式为8

让我们完成编译器的工作并构建我们的类。

首先,我们有m_number,占用4个字节。我们必须按照给定的顺序放置成员,因此m_number位于A的开头:

iiii

到目前为止,我们的大小为4(int的四个字节)和对齐4(因为int具有对齐4)。但是现在我们必须添加一个double(大小和对齐8)。由于直接在int之后,我们在(相对)地址4,我们没有正确对齐double,所以我们必须添加4个 padding 字节(我将用{{1}标记})得到8的倍数。因此我们得到了我们的班级:

*

现在,如果该类用作基类,我们就完成了。因此我们有iiii****dddddddd base size=16(我们需要对齐8才能正确对齐)。

对于完整的对象,还有另一个考虑因素:标准要求在数组中,对象彼此跟随,两者之间没有间隙。也就是说,对象之后的第一个字节必须正确对齐下一个对象。这最终意味着整个对象的大小必须是其对齐的倍数。

现在我们发现的对象布局已经满足了这个要求。因此,对于完整的对象,我们也可以不改变地使用它。因此,我们会获得完整对象的base align=8size=16

现在考虑订单逆转的情况:

align=8

现在我们必须从class A { double m_nothing; int m_number; }; 开始:

double

接下来,我们必须添加dddddddd 。事实证明,下一个空闲位置已经正确对齐int,因此我们可以添加它:

int

现在我们已经准备好了作为基础对象使用。如您所见,我们只需要12个字节,因此ddddddddiiii 。当然,为了使base size=12正确对齐,对象必须再次从8的倍数开始。因此我们有double

然而,对于sue作为完整对象,我们现在发现下一个地址位于第12位, 正确对齐base align=8成员。因此,我们必须添加填充字节,直到我们再次到达正确对齐的地址:

double

如您所见,现在我们需要16个字节,因此ddddddddiiii**** 。由于双倍,我们仍然有size=16

请注意,对齐要求会显着影响类的大小。例如,考虑以下两种类型:

align=8

虽然两者都包含相同的成员,但struct S1 { char c1; double d1; char c2; double d2; char c3; }; struct S2 { double d1; double d2; char c1; char c2; char c3; }; 上面的尺寸和对齐的总(非基数)尺寸为40,而S1的总尺寸仅为24。 ,S2类型的对象将作为完整对象,看起来像

S1

而类型c*******ddddddddc*******ddddddddc******* 的那些看起来像

S2

所以底线是具有最高对齐要求的成员应该始终排在第一位。

另请注意,ddddddddddddddddccc***** 返回完整对象的大小,即类层次结构转储调用sizeof的内容。