c++ - 我如何理解fdump-class-hierarchy输出

标签 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):
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

最佳答案

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

大小只是它所占用的字节数。因此,size=16表示当用作完整类型时,它始终占用16个字节。

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

如果该类用作基类,则base sizebase align给出大小和对齐方式。它们之所以不同,是因为C++标准允许对象在用作基类时使用较少的填充。

因此,让我们具体看一下您的示例(在第一种情况下,我假设您实际上在int之前拥有double)。我还省略了publicprivate,因为在这里它们什么都不会更改(如果您同时拥有公共(public)或私有(private)数据成员,则它们原则上可以进行某些更改,但是我不知道是否有任何编译器会利用这一点)。我也在猜测intdouble的大小和对齐方式(实际上,我假定的值是相当普遍的选择,并说明您获得的值)。

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

class A
{
  int m_number;
  double m_nothing;
};

现在int具有大小和对齐方式4,而double具有大小和对齐方式8

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

首先,我们有m_number,它占用4个字节。我们必须按照给定的顺序排列成员,因此m_numberA的开头:
iiii

到现在为止,我们的大小为4(int的四个字节),并且对齐方式为4(因为int的对齐方式为4)。但是现在我们必须添加一个double(大小和对齐方式8)。由于紧接int之后,我们在(相对)地址4处,因此我们没有正确地为double对齐,因此我们必须添加4个填充字节(我将用*标记)以达到8的倍数。因此我们得到我们的类(class):
iiii****dddddddd

现在,如果将该类用作基类,那么我们就完成了。因此,我们将其设为base size=16base align=8(我们需要将8对齐以便正确地将double对齐)。

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

现在,我们发现的对象布局已满足该要求。因此,我们也可以将其不变地用于完整对象。因此,对于完整的对象,我们得到size=16align=8

现在考虑颠倒顺序的情况:
class A
{
  double m_nothing;
  int m_number;
};

现在我们必须从double开始:
dddddddd

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

现在可以用作基础对象了。如您所见,我们只需要12个字节,因此是base size=12。当然,为了正确地对齐double,对象必须再次从8的倍数的地址开始。因此,我们有了base align=8

但是,对于作为完整对象的起诉,我们现在发现下一个地址将位于位置12,该位置未针对double成员正确对齐。因此,我们必须添加填充字节,直到再次到达正确对齐的地址为止:
ddddddddiiii****

如您所见,现在我们需要16个字节,即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;
};

虽然两者都包含相同的成员,但是具有上述大小和对齐方式的S1的总(非基本)大小为40,而S2的总大小仅为24。实际上,S1类型的对象将作为完整对象, 看起来像
c*******ddddddddc*******ddddddddc*******

S2类型的代码看起来像
ddddddddddddddddccc*****

因此,最重要的是,具有最高对齐要求的成员应始终排在第一位。

还要注意sizeof返回完整对象的大小,即类层次结构转储调用的size

关于c++ - 我如何理解fdump-class-hierarchy输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17818556/

相关文章:

objective-c - 当我在运行时只知道类名时,如何获取类对象

c++ - MS C++ (CL) 编译的可执行文件不能在 Windows 2000 上运行

c++ - STL 算法是否使用多核?

c++ - rust中功能的类型删除

c++ - 为什么我可以有一个 std::vector<std::ofstream*> 但不能有一个 std::vector<std::ofstream> ?

c# - 如何使用 MySQL 数据填充包含每个类项的类列表的类列表?

c++ - 使用 CryptoPP 库加密和解密字节数组/vector

c++ - CUDA 在内核中对在主机上创建的对象调用虚拟方法

linux - 为什么堆栈段在树莓派上是可执行的?

gcc - 为什么常见的 C 编译器在输出中包含源文件名?