当我们写一个class类,然后sizeof(),然后发现这个值往往比你想象的大,这是为什么呢?这里就要讲到内存对齐的问题。
先来看一下内存对齐的几条原则:
1.对于class(struct/union)的各个成员,第一个数据成员放在偏移为0的地方,以后每个数据成员存储的其实位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始;
2.结构体作为成员时,结构体成员要从其内部最大元素大小的整数倍地址开始存储;
3.结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足要补齐。
下面看一个小例子:
#include<iostream> using namespace std; class student { private: int number;//0-3 double weight;//8-15 char name[10];//16-25 char sex[4];//26-29 };//补齐29-32 class student s; class teacher { private: int number;//0-3 char name[10];//4-13 char sex[4];//14-17 public: student s[2];//24-88 }; int main() { student s; teacher t; cout<<"student:"<<sizeof(s)<<endl; cout<<"teacher:"<<sizeof(t)<<endl; return 0; }
(补充讲一下,“student s[2]”是从24开始的,因为s的子成员weight的大小是8,所以从它的整数倍,也就是24开始。)
结果是:
student: 24
teacher: 88
下面就来解释一些疑问:
1.什么是对齐?
现代计算机中内存空间都是按照byte划分的,从理论上讲对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
2.为什么要对齐呢?
硬件限制:不是所有的硬件平台都能访问任意地址上的数据;某些硬件平台只能在某些地址取特定类型的数据,否则抛出硬件异常。
提高性能:内存对齐后,CPU的内存访问速度大大提升。
3.那些情况要考虑内存对齐?
在不同平台之间(比如windows和linux),不同模块之间(dll与exe)传递二进制流(如结构体),必须要定义相同的对齐方式。
序列化与反序列化的操作时,也必须要定义相同的对齐方式。
OK.