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

Posted

技术标签:

【中文标题】为啥类的大小取决于成员声明的顺序?如何?【英文标题】:Why does the size of a class depends on the order of the member declaration? and How?为什么类的大小取决于成员声明的顺序?如何? 【发布时间】:2013-05-03 14:37:54 【问题描述】:

有人解释一下类中成员声明的顺序如何决定该类的大小。

例如:

class temp

public:
    int i;
    short s;
    char c;
;

上述类的大小为8字节。

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

class temp

public:
    char c;
    int i;
    short s;
;

那么类的大小是12字节。

怎么做?

【问题讨论】:

见data structure alignment 【参考方案1】:

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

因此,如果您在 int 之前声明了一个 1 字节的字符(此处假设为 4 字节),则中间将有 3 个空闲字节。用于它们的常用术语是“填充”。

Data structure alignment

Another good pictorial explanation

对齐原因

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

强制编译器避免对齐的一种方法是(特定于 gcc/g++)将关键字“packed”与结构属性一起使用。 packed keyword 该链接还指定了如何使用 aligned 关键字按照您选择的特定边界(2、4、8 等)强制对齐。

最佳实践

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

另一个有用的SO question on performance advantage of alignment

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

class temp

public:
    int i;
    short s;
    char c;
    char c2;
;

【讨论】:

这是对数据结构对齐的一个很好的解释。谢谢你。 没问题!随时。我对此非常了解,因为曾经在一个关键的嵌入式项目中,我们有一个我们匆忙创建的演示应用程序。由于懒惰并考虑到它的演示,我们通过地址索引初始化了一个数组,即类似 array = "first", "second", "third";最糟糕的部分是它最初运行良好,但在特定目标平台上失败,后来才发现原因是填充。所以这是一个重要的教训。如果其他人能避免同样的错误,我会非常高兴。【参考方案2】:
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) 中的填充

【讨论】:

以上是关于为啥类的大小取决于成员声明的顺序?如何?的主要内容,如果未能解决你的问题,请参考以下文章

类成员的编译顺序之嵌套类型对类的影响

为啥派生类的朋友不能使用受保护的成员?

深入理解类

类的组合

C++ OOP Feature Conclusion (更新中)

java程序执行顺序