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

Why does the size of a class depends on the order of the member declaration? and How?

本文关键字:顺序 成员 取决于 为什么 声明      更新时间:2023-10-16

有人向我解释了类内成员声明的顺序如何决定该类的大小。

例如:

class temp
{
public:
    int i;
    short s;
    char c;
};

上述类的大小为8字节。

但当成员声明的顺序更改为以下时

class temp
{
public:
    char c;
    int i;
    short s;
};

则类的大小是12个字节。

如何?

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

因此,如果在int之前声明了一个1字节的字符(此处假定为4字节(,那么在这两个字符之间将剩下3个空闲字节。对它们常用的术语是"填充"。

数据结构对齐

另一个很好的图片解释

对齐原因

填充允许更快的内存访问,即对于cpu来说,访问对齐的内存区域更快。例如,读取一个4字节对齐的整数可能需要一次读取调用,其中,如果一个整数位于未对齐的地址范围(例如地址0x0002-0x0006(,则需要两次内存读取才能获得该整数。

强制编译器避免对齐的一种方法是(特定于gcc/g++(在structure属性中使用关键字">packed"。packed关键字该链接还指定如何使用aligned关键字通过您选择的特定边界(2、4、8等(强制对齐。

最佳实践

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

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

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

class temp
{
public:
    int i;
    short s;
    char c;
    char c2;
};
class temp 
{
public:
   int i;   //size 4 alignment 4
   short s; //size 2 alignment 2
   char c;  //size 1 alignment 1
}; //Size 8 alignment max(4,2,1)=4

temp[i[0-4]s[4-2]c[6-7]]->8填充(7-8(

class temp 
{
public:
    char c;  //size 1 alignment 1
    int i;   //size 4 alignment 4
    short s; //size 2 alignment 2
};//Size 12 alignment max(4,2,1)=4

temp[c[0-1]i[4-8]s[8-10]]->12填充(1-4(和(10-12(