一文讀懂C++內存對齊

操作系統64位和32位有什麼區別?

  • 64位操作系統意味着其cpu擁有更大的尋址能力。理論上來說,其性能相比於32位操作系統會提升1倍。但是這也需要在64位操作系統上運行的軟件也是64位的。
  • 軟件中數據類型的的字節數大小其實和操作系統是多少位的沒有關係,而是由編譯器決定的。也就是說數據結構佔多少位取決於在軟件編譯時我們選擇的是64位還是32位的編譯器。其具體佔位數在編譯器已經決定了。

數據類型對應字節數

  • 下面是不同位數編譯器下基本數據類型對應的字節數。

32位編譯器:

char :1個字節
char*(即指針變量): 4個字節
short int : 2個字節
int:  4個字節
unsigned int : 4個字節
float:  4個字節
double:   8個字節
long:   4個字節
long long:  8個字節
unsigned long:  4個字節

64位編譯器:

char :1個字節
char*(即指針變量): 8個字節
short int : 2個字節
int:  4個字節
unsigned int : 4個字節
float:  4個字節
double:   8個字節
long:   8個字節
long long:  8個字節
unsigned long:  8個字節
  • 總結:32位和64位編譯器的基本數據類型字節數主要差別在64位的指針和long爲8字節。

C++內存對齊

  • 衆所周知,爲了保證每個對象擁有彼此獨立的內存地址,C++空類的內存大小爲1字節。而非空類的大小與類中非靜態成員變量和虛函數表的多少有關。其中,類中非靜態成員變量的大小則與編譯器的位數以及內存對齊的設置有關。

  • 類中的成員變量在內存中並不一定是連續的。它是按照編譯器的設置,按照內存塊來存儲的,這個內存塊大小的取值,就是內存對齊。

  • 內存對齊有2個規則:

    • 第一個成員變量放在類中內存offset爲0的地方,之後的成員變量的對齊按照#pragma pack(n)指定的數值和這個成員變量類型所佔字節數中,比較小的那個進行(成員變量間補齊)。

    • 在成員變量完成各自內存對齊之後,類(結構或聯合)本身也要進行內存對齊,對齊按照#pragma pack(n)指定的數值和類中最大成員變量類型所佔字節數中,比較小的那個進行(類中最後一個成員變量結尾後補齊),類大小需要是對齊值得整數倍。

  • #pragma pack(n)作爲一個預編譯指令用來設置內存對齊的字節數。需要注意的是,n的缺省數值是編譯器設置的,一般爲8,合法的數值分別是1、2、4、8、16。

延伸知識:C++空類大小

  • C++標準指出,不允許一個對象(當然包括類對象)的大小爲0,不同的對象不能具有相同的地址。這是由於:

    • new需要分配不同的內存地址,不能分配內存大小爲0的空間
    • 避免除以sizeof(T)時得到除以0錯誤故使用一個字節來區分空類。
  • 需要注意的是,這並不代表一個空基類也需要加一個字節到子類中去。這種情況下,空基類並不是獨立的,它附屬於子類。子類繼承空基類後,子類如果有自己的數據成員,則空基類的那一個字節並不會加到子類中去。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章