为什么类的大小取决于成员声明的顺序?如何?

Mur*_*gan 20 c c++ padding memory-alignment

有人解释我如何在类中的成员声明的顺序决定该类的大小.

例如 :

class temp
{
public:
    int i;
    short s;
    char c;
};
Run Code Online (Sandbox Code Playgroud)

上面这个类的大小是8个字节.

但是当成员声明的顺序改变如下

class temp
{
public:
    char c;
    int i;
    short s;
};
Run Code Online (Sandbox Code Playgroud)

那么类的大小是12个字节.

怎么样?

fkl*_*fkl 37

上述行为背后的原因是数据结构对齐和填充.基本上,如果要创建一个4字节变量,例如int,它将与四字节边界对齐,即它将从内存中的地址开始,该地址是4的倍数.同样适用于其他数据类型.2字节短路应从偶数存储器地址开始,依此类推.

因此,如果你在int之前声明了一个1字节的字符(假设这里是4字节),那么它们之间将剩下3个空闲字节.用于它们的常用术语是"填充".

数据结构对齐

另一个很好的图解说明

对齐的原因

填充允许更快的内存访问,即对于cpu,访问对齐的内存区域更快,例如读取4字节对齐的整数可能需要单个读取调用,就好像整数位于非对齐的地址范围(例如地址0x0002 - 0x0006) ,那么需要两次内存读取来获得这个整数.

强制编译器避免对齐的一种方法是(特定于gcc/g ++)使用关键字' packed '和structure属性.packed关键字此外,该链接还指定了如何使用aligned关键字按您选择的特定边界(2,4,8等)强制对齐.

最佳实践

以变​​量已经与最小填充对齐的方式构造类/结构总是一个好主意.这减少了整体类的大小,加上它减少了编译器完成的工作量,即没有重新排列结构.还应始终按代码中的名称访问成员变量,而不是尝试从结构中读取特定字节,假设值将位于该字节.

关于对齐性能优势的另一个有用的SO问题

为了完成,在你的场景(32位机器)中,下面仍然会有8个字节的大小,但它不会变得更好,因为现在占用了8个字节,并且没有填充.

class temp
{
public:
    int i;
    short s;
    char c;
    char c2;
};
Run Code Online (Sandbox Code Playgroud)

  • 没问题!随时.我对此非常了解,因为曾经在一个关键的嵌入式项目中,我们有一个我们匆忙创建的演示应用程序.由于懒惰并考虑它演示,我们通过地址索引初始化一个数组,例如array = {"first","second","third"}; 最糟糕的是它最初工作正常并且在特定目标平台上失败,只有后者才揭示原因是填充.所以这是一个重要的教训.如果其他人可以避免同样的错误,我会很高兴. (2认同)