資料結構:結構體在繼承中資料記憶體排列探究
阿新 • • 發佈:2019-02-19
下面以一個例子來說明(為了方便,結構體命名方面就馬虎點了):
#ifndef _STRUCTTEST_H_ #define _STRUCTTEST_H_ typedef struct tag_Base { int s32Count; char byNone; bool bYes; long dwTemp; tag_Base() { s32Count = 100; byNone = 'Y'; bYes = true; dwTemp = 200; printf("Base created!\n"); }; }TBase; typedef struct tag_Base2 { int s32Count; char byNone; long dwTemp; bool bYes; tag_Base2() { s32Count = 100; byNone = 'Y'; bYes = true; dwTemp = 200; printf("Base2 created!\n"); }; }TBase2; typedef struct tag_InheritBase : public TBase { char byIyes; int dwItemp; tag_InheritBase() { byIyes = '0'; dwItemp = 1023; printf("Tinherit has been created!\n"); } }Tinherit; typedef struct tag_InheritBase2 : public TBase2 { char byIyes; int dwItemp; tag_InheritBase2() { byIyes = '0'; dwItemp = 1023; printf("Tinherit has been created!\n"); } }Tinherit2; #endif // !_STRUCTTEST_H_
1. 在VS2013環境,編譯器為:MS VC++ 12.0
tag_Base結構體的大小是4+4+4
以一次實驗資料舉例,其在記憶體中的儲存特性如下:
0x00A6FE74 |0x64 0x00 0x00 0x00 ##大端還是小端看的出來哦,0x00A6FE78 |0x59 0x01 0xcc 0xcc ##第二個4位元組,先存char然後在存的bool
0x00A6FE7C |0xc8 0x00 0x00 0x00
tag_Base2幾乎與TBase一樣,只是順序有點變動,所以佔的位元組數也就不同了(4+4+4+4)
同樣是一個例項,觀察其在記憶體中的排列:
0x0013F060 |0x64 0x00 0x00 0x000x0013F064 |0x59 0xcd 0xcd 0xcd
0x0013F068 |0xc8 0x00 0x00 0x00
0x0013F06C |0x01 0xcd 0xcd 0xcd
對於結構體的繼承:
Tinherit繼承與TBase結構體,其佔用空間為20:
(4+4+4+4+4),以下為例項:
0x0111DAB8 |0x64 0x00 0x00 0x00 (int)0x0111DABC |0x59 0x01 0xcd 0xcd (char)(0x0111DABD|bool)
0x0111DAC0 |0xc8 0x00 0x00 0x00 (long)
0x0111DAC4 |0x30 0xcd 0xcd 0xcd (char)
0x0111DAC8 |0xff 0x03 0xcd 0xcd (int)
Tinherit2繼承與TBase2結構體,其佔用空間為24:
(4+4+4+4+4+4),以下為例項:
0x00ABDAD0 |0x64 0x00 0x00 0x00 (int s32Count)
0x00ABDAD4 |0x59 0xcd 0xcd 0xcd (char byNone)
0x00ABDAD8 |0xc8 0x00 0x00 0x00 (long dwTemp)
0x00ABDADC |0x01 0xcd 0xcd 0xcd (bool bYes)
0x00ABDAE0 |0x30 0xcd 0xcd 0xcd (char byIyes)
0x00ABDAE4 |0xff 0x03 0xcd 0xcd (int dwItemp)
由此可見結構體的繼承中,其父結構體與子結構體在記憶體中的排列,是父類在前,子類在後,且在該種編譯環境下父類與子類不會採用緊湊排列方法。
2. 編譯器gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)
本文同時嘗試過不同編譯器環境下,對資料結構的排列的影響。採用Linux系統下的G++編譯器,編譯器版本為gcc version 3.4.6 20060404 (Red Hat 3.4.6-11)實驗結果摒棄相同的部分,不同之處在於,對於Tinherit2結構體的排列,Linux系統採用了緊湊排列的方式,例項如下:0x9c54008 |0x64 0x00 0x00 0x00 (int s32Count)0x9c5400C |0x59 0xcd 0xcd 0xcd (char byNone)
0x9c54010 |0xc8 0x00 0x00 0x00 (long dwTemp)
0x9c54014 |0x01 0x30 0xcd 0xcd (bool bYes)(0x9c54015|char byIyes)
0x9c54018 |0xff 0x03 0xcd 0xcd (int dwItemp)
結論:
1. 結構體的繼承中,父結構體的成員資料排在子結構體之前
2. 對於不同的平臺,結構體整體資料儲存優化類似,但是不同編譯器之間父與子的資料是否緊湊排列有所不同