一個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 ()來恢復為默認的對齊方式。