C++結構體可以繼承!struct

問題引入

C++結構體可以繼承!struct/class等內存字節對齊問題詳解

如下結構體:

C++結構體可以繼承!struct/class等內存字節對齊問題詳解

更多C/C++學習資料,請私信我“代碼”,即可獲取

那麼一個這樣的結構體變量佔多大內存呢?也就是:cout<會輸出什麼?在瞭解字節對齊方式之前想當然的會以為:

sizeof(Stu) = sizeof(int)+sizeof(char)+sizeof(float) = 9.

然而事實並非如此!

字節對齊原則

在系統默認的對齊方式下:每個成員相對於這個結構體變量地址的偏移量正好是該成員類型所佔字節的整數倍,且最終佔用字節數為成員類型中最大佔用字節數的整數倍

在這個例子中,id的偏移量為0(0=4*0),sex的偏移量為4(4=1*4),hight的偏移量為8(8=2*4),此時佔用12字節,也同時滿足12=3*4.所以sizeof(Stu)=12.

出現繼承關係時

C++結構體可以繼承!struct/class等內存字節對齊問題詳解

更多C/C++學習資料,請私信我“代碼”,即可獲取

基類的成員總是在派生類的前面。而且即使有字節對齊,基類對齊後派生類的成員不會佔用基類填充的字節,即計算好基類所佔字節數後,這些字節只能由基類擁有,不能被派生類的成員佔用(即char b後面有3字節的填充,之後才有char c)在派生類中成員的分佈只需滿足每個變量起始字節序號為該類型所佔字節數的整數倍且最終大小為佔用字節數最大的類型對應的字節數的整數倍。排列如下:

C++結構體可以繼承!struct/class等內存字節對齊問題詳解

更多C/C++學習資料,請私信我“代碼”,即可獲取

關聯關係

 必須滿足:

1.結構體/類與結構體/類之間不會共用自動補齊的內存,即一個結構體變量/對象對齊之後填補的內存不允許被其他變量/對象佔用;

2.結構體的起始字節位置必須是該結構體中所佔字節數最大的變量的字節數的整數倍;

3.最終所佔字節數必須是最大所佔字節數最大的變量的字節數的整數倍。

強制對齊

當然,有時候考慮到其他特殊用途,使用#pragma pack(n)來設定以n字節對齊的方式(n可取2的較小次冪,即1,2,4,8,具體取值範圍以及默認值與所使用的編譯器有關。筆者所測試的環境下vs/vc默認為8,gcc默認為4)。

n字節對齊就是說變量存放的起始地址的偏移量有兩種情況:

  • 如果n大於等於該變量所佔用的字節數,那麼偏移量必須滿足默認的對齊方式;
  • 如果n小於該變量的類型所佔用的字節數,那麼偏移量為n的倍數,不用滿足默認的對齊方式。

結構的總大小也有個約束條件,分下面兩種情況:如果n大於所有成員變量類型所佔用的字節數,那麼結構的總大小必須為佔用空間最大的變量佔用的空間數的倍數;否則必須為n的倍數。比如有以下代碼:

C++結構體可以繼承!struct/class等內存字節對齊問題詳解

更多C/C++學習資料,請私信我“代碼”,即可獲取

這時候編譯器就會被迫使用我們約定的字節對齊方式,即4字節對齊,因此c1佔4字節,d佔8字節,i佔4字節,c2佔4字節,共20字節;

如果我們沒有設置字節對齊方式,仍然使用默認對齊的話,這裡sizeof(Test) = 24。

C++類對齊原則

C++結構體可以繼承!struct/class等內存字節對齊問題詳解

更多C/C++學習資料,請私信我“代碼”,即可獲取

  • 在不考慮(或者說在沒有)虛函數和虛繼承的情況下,sizeof(自定義類)也按照類似上面的方式來計算。
  • 如果一個類擁有虛函數或者虛繼承,則在數據成員的基礎上相當於多一個指針類型的數據成員(位置在所有數據成員的前面),最後計算時加上即可。
  • 如果一個類或者結構體不含有任何數據成員,且無虛函數以及虛繼承,則sizeof()結果為1。
  • 靜態成員不在計算範圍。

更多精彩

C++結構體可以繼承!struct/class等內存字節對齊問題詳解


分享到:


相關文章: