目录
- 定义
- example
- class和struct在内存对齐方面的相似性
定义
- 内存对齐是指编译器在为结构体或类的成员分配内存时,按照一定的规则将成员存放在特定的内存地址上,使得每个成员的起始地址是某个特定值(通常是成员自身大小或一个指定对齐值的倍数),结束时也要内存也要对齐
- 每个特定平台上的编译器都有自己的默认“对齐系数”(32位机一般为4,64位机一般为8)
- 我们可以通过预编译命令
#pragma pack(k)
,k=1,2,4,8,16来改变这个系数,其中k就是需要指定的“对齐系数” - 也可以使用#pragma pack()取消自定义字节对齐方式。
- 对齐按照对齐系数和自身占用字节数中,二者比较小的那个进行对齐
example
#pragma pack(4)
struct One{double d;char c;int i;
}
struct Two{char c;double d;int i;
}
struct Three{char c;double d;char i;
};
class和struct在内存对齐方面的相似性
- 访问权限对内存对齐的不影响
class
有访问权限控制(如public
、private
、protected
),而struct
默认成员是public
。但这些访问权限的设置不会影响内存对齐。无论成员是public
还是private
,编译器在进行内存布局时,只关注成员的数据类型和当前的对齐设置。- 例如,在一个
class
中,private
成员和public
成员在内存中的存储位置和填充方式是相同的,遵循相同的内存对齐规则。
- 继承对内存对齐的影响
- 单一继承情况:在
class
和struct
进行单一继承时,基类和派生类的成员在内存中的布局也会遵循内存对齐规则。派生类的内存布局通常是先存储基类的成员,然后是派生类自身的成员,在这个过程中,每一个成员(无论是基类的还是派生类的)都会根据其自身的数据类型和当前对齐设置进行存储,中间可能会插入填充字节。 - 多重继承情况:对于多重继承,情况会更加复杂。编译器需要按照一定的规则来安排多个基类成员和派生类成员的存储位置,并且保证每个成员都满足内存对齐要求。在这种情况下,不同编译器的实现可能会略有差异,但总体上还是遵循内存对齐的基本原则,尽量减少访问数据时的性能损失。
- 虚函数对内存对齐的影响(主要针对class)
- 如果一个
class
包含虚函数,编译器会为该class
添加一个虚函数表指针(通常是一个指针大小,在32位系统中为4字节,在64位系统中为64字节)。这个虚函数表指针的位置和类中的其他成员一样,也会遵循内存对齐规则。一般情况下,它会被放置在类对象内存布局的开头(在某些编译器实现中),并且会影响整个类对象的内存大小和布局。例如,一个只有虚函数的class
对象,其大小至少是一个指针大小(用于存储虚函数表指针),并且会根据当前的对齐设置进行内存对齐。而struct
如果没有类似虚函数的特性,就不会有这个虚函数表指针相关的内存布局变化。