类的大小:
类的大小只与成员变量(非static数据成员变量)和虚函数指针有关,还要考虑到对齐。
对齐规则理解1:
1.数据成员对齐规则:struct, union的数据成员,第一个数据成员放在offset为0的地方,之后的数据成员的存储起始位置都是放在该数据成员大小的整数倍位置。如在32bit的机器上,int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。
2.结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。
3.收尾工作的对齐规则:整个struct的大小,应该为最大数据成员大小的整数倍。
假设在64位机器下
class test1 {
int a; //内存位置:[0]..[3]
char b; //内存位置:[4]
int* c; //内存位置:[8]..[15]
}
sizeof(test1) = 16
class test2 {
short x; //内存位置:[0]..[1]
double y; //内存位置:[8]..[15]
test1 t; //内存为止:[16]..[32]
char z; //内存为止:[17]
}
sizeof(test2) = 2 + (6) + 8 + 16 + 1 + (7) = 40
对齐规则理解2:
#include<iostream> using namespace std; class test { private : char c='1';//1byte int i;//4byte short s=2;//2byte }; int main(){ cout << sizeof(test) << endl; return 0; }
输出:12
class test2 { private: int i;//4byte char c = '1';//1byte short s = 2;//2byte }; int main(){ cout << sizeof(test2) << endl; return 0; }
输出:8
我们可以看到。类test和test2的成员变量完全一样,只是定义顺序不一样,却造成了2个类占用内存大小不一样。而这就是编译器内存对齐的缘故。
(1)对于类test的内存空间是这样的:
内存分配过程:
1、char和编译器默认的内存缺省分割大小比较,char比较小,分配一个字节给它。
2、int和编译器默认的内存缺省分割大小比较,int比较小,占4字节。只能空3个字节,重新分配4个字节。
3、short和编译器默认的内存缺省分割大小比较,short比较小,占2个字节,分配2个字节给它。
4、对齐结束类本身也要对齐,所以最后空余的2个字节也被test占用。
(2)对于类test2的内存空间是这样的:
1、int和编译器默认的内存缺省分割大小比较,int比较小,占4字节。分配4个字节给int。
2、char和编译器默认的内存缺省分割大小比较,char比较小,分配一个字节给它。
3、short和编译器默认的内存缺省分割大小比较,short比较小,此时前面的char分配完毕还余下3个字节,足够short的2个字节存储,所以short紧挨着。分配2个字节给short。