c++內(nèi)存對(duì)齊--GeekBand

c++中每個(gè)class包含兩部分:數(shù)據(jù)和函數(shù)。對(duì)每個(gè)對(duì)象來(lái)說(shuō)函數(shù)部分大家公用一份,而數(shù)據(jù)部分每個(gè)對(duì)象是獨(dú)立的。所以在求一個(gè)class所占的空間大小的時(shí)候,求得數(shù)據(jù)部分所占的內(nèi)存大小即為class的大小。下面小將結(jié)合實(shí)驗(yàn)的方式測(cè)試驗(yàn)證,考慮到vs下編譯器和gcc的不同,小編這里分別獨(dú)立驗(yàn)證,vs編譯器驗(yàn)證采用vs2013IDE,gcc下的驗(yàn)證用codeblocks,測(cè)試都是在32系統(tǒng)下。class Fruit{
int no;
double weight;
char key;public:
void print() { }
virtual void process(){ }
};
所以這里的Fruit類,no是int型,占4個(gè)字節(jié)(實(shí)驗(yàn)是在32系統(tǒng)下,下面也是),weight是double型占8個(gè)字節(jié),key是字符型占1個(gè)字節(jié),別忘了這里有個(gè)虛函數(shù),有一個(gè)隱藏的虛函數(shù)指針占4個(gè)字節(jié)。所以4+8+1+4=17個(gè)字節(jié)。
真是這么多嗎,用sizeof測(cè)試下就知道了,在vs2013下sizeof(Fruit)==32.具體是怎么分配的呢?實(shí)驗(yàn)驗(yàn)證如下:

1.png

可以看到,指向虛函數(shù)的指針?biāo)嘉恢檬菑钠屏?位置開始的,占用8個(gè)字節(jié)。no變量從偏移量8位置開始,占用4個(gè)字節(jié),但為了對(duì)齊,這里又分配了4個(gè)字節(jié)(alignment member)(size=4)。weight從偏移量16開始,占用8個(gè)字節(jié)。key從偏移量24開始,占用一個(gè)字節(jié),但這里為了對(duì)齊,又分配了7個(gè)字節(jié)。所以共占用8+4+4(對(duì)齊)+8+1+7(對(duì)齊)=32字節(jié)。

vs2013下Fruit類和Apple類占用內(nèi)存大小
有繼承的情況占用的內(nèi)存情況又是什么樣的呢?比如下面的代碼,Apple所占用的空間是多少呢?
class Apple : public Fruit{
int size;
char type;
public:
void save() { }
virtual void process(){ }
};
vs2013下實(shí)際測(cè)試sizeof(Apple)==40,具體是怎么分配的,驗(yàn)證結(jié)果如下

2.png

可以看到,Apple繼承了Fruit數(shù)據(jù),F(xiàn)urit部分所占用的空間是32字節(jié),Apple類本身的size占4個(gè)字節(jié),type 是占1個(gè)字節(jié),但為了對(duì)齊多占了3個(gè)字節(jié)。

codeblocks(gcc)下Fruit類和Apple所占內(nèi)存大小
同樣是上面的Furit類和Apple,通過(guò)下面的代碼測(cè)試

int main()
{
cout<<sizeof(Fruit)<<endl;
cout<<sizeof(Apple)<<endl;
return 0;
}
測(cè)試結(jié)果為:

codeblocks內(nèi)存.png

哪在gcc下為什么Fruit類為什么是24字節(jié)呢?
虛函數(shù)指針(4字節(jié))+no(4字節(jié))+weight(8字節(jié))+key(1字節(jié),為了對(duì)齊添加了7字節(jié))=24字節(jié)
哪gcc下Apple類是32字節(jié)是怎么來(lái)的呢?
虛函數(shù)指針(4字節(jié))+no(4字節(jié))+weight(8字節(jié))+key(1字節(jié),為了對(duì)齊添加了3字節(jié))+size(4字節(jié))+type(1字節(jié),為了對(duì)齊添加了7字節(jié))=32字節(jié)

為什么vs2013下和codeblocks下Fruit類和Apple類所占用的空間不同呢?
這是因?yàn)関s2013是微軟的vc編譯器,codeblocks是gcc編譯器。兩者在對(duì)齊的時(shí)候采用的策略不同。vs2013下采用的是以最大變量所占用的字節(jié)為標(biāo)準(zhǔn),即以double型的weight為標(biāo)準(zhǔn),所以Fruit類中int型的no不足8字節(jié)都會(huì)補(bǔ)足到8字節(jié),所以no補(bǔ)了4字節(jié)。char型的key補(bǔ)了7字節(jié)。在Apple類中最大變量是int型的size,所以type補(bǔ)了3字節(jié)。
gcc就不是以這樣的標(biāo)準(zhǔn),gcc對(duì)齊重點(diǎn)兩點(diǎn),
1)變量的偏移位置是該變量所占內(nèi)存的整數(shù)倍,如果不滿足則補(bǔ)齊,size不滿足,所以key補(bǔ)了3字節(jié)
2)所有變量占的字節(jié)數(shù)是最大變量所占字節(jié)的整數(shù)倍,如果不滿足則補(bǔ)齊,所有type補(bǔ)了7字節(jié)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容