有人向我解释了类中成员声明的顺序如何决定该类的大小。
例如 :
class temp
{
public:
int i;
short s;
char c;
};
上述类的大小为 8 个字节。
但是当成员声明的顺序改变如下
class temp
{
public:
char c;
int i;
short s;
};
那么类的大小是 12 个字节。
如何?
有人向我解释了类中成员声明的顺序如何决定该类的大小。
例如 :
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++)将关键字“ packed ”与结构属性一起使用。打包关键字该链接还指定了如何使用对齐关键字按照您选择的特定边界(2、4、8 等)强制对齐。
最佳实践
以变量已经与最小填充对齐的方式构造类/结构总是一个好主意。这减少了整个类的大小,加上它减少了编译器完成的工作量,即没有重新排列结构。此外,应该始终通过代码中的名称访问成员变量,而不是尝试从结构中读取特定字节,假设值位于该字节处。
关于对齐的性能优势的另一个有用的 SO 问题
为了完整起见,在您的场景(32 位机器)中,following的大小仍然为 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
温度[我[0-4];年代[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
温度 [ c [0-1]; 我[4-8];s [8-10]]] -> 12 填充 (1-4) 和 (10-12)