一个Class对象需要占用多大的内存空间?
非静态成员变量总合。(not static)
加上编译器为了CPU计算,作出的数据对齐处理。
加上为了支持虚函数(virtual function),产生的额外负担。
下面我们主要讨论下C的数据对齐处理。
首先,为简单起见,我们先讨论在没有#pragam pack宏的情况下,内存对齐的三条规则:
数据成员对齐规则:第一个数据成员放在offset为0的地方,之后的数据成员的存储起始位置都是放在该数据成员大小的整数倍位置上。比如在32bit的机器上,int的大小为4,因此int都是从4的整数倍的位置开始存储。
结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的【最大数据成员】大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。
收尾工作的对齐规则:整个struct的大小,应该为最大数据成员大小的整数倍(如果含有struct B,这里的数据成员中B不是作为一个数据成员,而是以B内部的成员来算,比如B的size为40,其内部最大为double,则A的最大应该是8,而不是40)。
例子:
struct A
{
char a; //内存位置: [0]
double b; // 内存位置: [8]...[15]
int c; // 内存位置: [16]...[19] ---- 规则1
};
//总大小:sizeof(A) = 24, 补齐[20]...[23] ---- 规则3
struct B
{
int a; // 内存位置: [0]...[3]
A b; // 内存位置: [8]...[31] ---- 规则2
char c; // 内存位置: [32]
};
//总大小:sizeof(B) = 40, 补齐[33]...[39]
理解了上面,我们再看看有#pragam pack宏的情况:
宏#pragma pack (n)的作用是按n字节对齐.实际上是取成员自身的对齐数和n中的较小者来作为对齐数(比如n=4,则double按4对齐而不是8),所以n为1的话就相当于取消对齐了。
可以用#pragma pack ()来恢复为默认的对齐方式。