在c++中的某乙個類的記憶體大小是由以下三部分組成:
1:nonstatic data member的總和大小
2:alignment所填補的空間,可能存在於members之間,也可能是類的邊界
3:為了支援virtual而由內部產生的額外負擔,比如:指虛基類表的指標或指向虛函式表的指標
其中1和3都比較好確定,比較難確定的是2中的記憶體對齊(填補)的大小
以下的分析都是visual stdio編譯器進行分析
alignment在類中對齊規則是:
一、先按照自身的資料型別進行對齊,再按照整個類的資料型別進行對齊。記憶體對齊中自身資料型別對齊很重要的一點是:自身的資料型別大小是多少,則儲存位址的起始位置則是它的倍數!比如:int大小是4位元組,則儲存int型別的起始記憶體位置必須是4的倍數,0x0000,0x0008,0x0016等
二、自身資料型別就是型別本身的大小(也可以為是型別本身大小的倍數),比如int就是4,char就是1。。。。
三、整個類的資料型別對齊大小為類中非靜態資料成員中型別最大的大小,比如
class a
char ch;
int a;
double d;
}則a類的對齊大小為8。
例子分析:
以上述a類為例
ch在0x0000位置上,a為int型別,它的起始記憶體位置要為4的倍數,所以應該為0x0004,於是0x0001,0x0002,0x0003三個位元組就被填充了。最後a佔了0x0004,0x0005,0x0006,0x0007。在要佔據8個位元組,所以記憶體的起始位置應該是0x0008,剛好符合。前面是按照自身資料型別對齊,後面要按照整個類的資料型別對齊,而類的資料型別為8,a類佔據了0x0000-0x00015。總共大小為16,剛好是8的倍數,所以整個a類記憶體對齊完畢。所以sizeof(a)=16;
class b
int a;
double d;
char ch;
跟上面一樣分析,a佔據了4個位元組,為了滿足d記憶體起始位置是8的倍數,所以a後面填補了4位元組,加上d的8位元組,最後ch大小為1位元組,可以直接存入,總共為4(a的大小)+4(填補)+8(d的大小)+1(ch的大小)=17。最後整個資料型別對齊是8的倍數,所以17+7=24;所以sizeof(b)=24。
四、總結:a和b資料成員相同,僅僅是因為成員順序不同,所以整個記憶體大小就不同。原因是因為記憶體對齊。
補充:1:指標(包括指向虛函式表的指標vfptr和指向虛類表的指標vbptr)是單獨與
整個類的資料進行對齊(與類成員變數中位元組最大的成員的記憶體大小對齊)。若類的資料對齊大小是小於等於4的,就直接是4,
因為vfptr大小是4。比如:class a則vfptr
應該與d的記憶體大小8位元組對齊;class a則vfptr直接與自身大小4對齊。
且vfptr是在類記憶體的非靜態資料成員的前面。
2:在單一的非虛繼承中,vfptr都是來自於基類!!所以vfptr只指向虛函式表中基類的部分
!若重寫虛函式,則覆蓋掉虛函式表裡基類部分對應的虛函式位址。這就實現了多型
且基類指標不能呼叫屬於派生自己的虛函式
3:在虛繼承中,若派生類的虛函式有不是重寫基類的虛函式,則派生類中有自己的vfptr,不從基類中繼承
;若全是重寫基類的虛函式則派生類的vfptr從基類中繼承
C 類的記憶體對齊
記憶體對齊。對下面的類 class b 大家可以猜一下類 b物件的大小。如果你猜是18 4 2 8 4 也不能說你錯。但是你用 sizeof b 一看,結果竟然是 24!多出來的 6個位元組是怎麼回事呢?其實是記憶體對齊搞的鬼。在編譯器的結構成員對齊設定為預設的情況下,分配給各個成員變數的記憶體大小...
C 類中的記憶體對齊
在沒有 pragma pack巨集的情況下 1.資料成員對齊規則 struct,union的資料成員,第乙個資料成員放在offset為0的地方,之後的資料成員的儲存起始位置都是放在該資料成員大小的整數倍位置。如在32bit的機器上,int的大小為4,因此int儲存的位置都是4的整數倍的位置開始儲存。...
C 類 記憶體對齊和類大小理解
首先,預設的塊對齊長度是4位元組,此外也可以通過 pragma pack x 修改,同時,自己修改完之後記得使用 pragma pack 恢復預設值。此外,又分了幾種情況 1 如果有虛函式,則會儲存虛函式表的位址 僅乙個位址,4位元組或8位元組 該位址是存放在類記憶體的最開始的地方。2 如果出現比x...