這裡記錄一下怎麼計算類物件的大小。
大概總結下,類的大小需要考慮以下內容:
非靜態成員變數大小
資料對齊到多少位
有無虛函式(即需不需要指向虛函式表的指標,如果考慮繼承的情況,則還需要看繼承了多少個指向虛函式表的指標)
首先我們看什麼都沒有的時候的例子:
可以看到,類例項化的物件的大小為1。這是因為即使類是空白類,編譯器也會分配乙個位元組的空間來佔位,用來和真正的空白/空變數區別開來(畢竟例項化其實就是分配一定的記憶體空間,如果沒有分配空間,那麼就和沒有例項化差不多了)。不過注意的是,如果空白類作為基類被繼承了的話,是不會對繼承它的類的空間產生影響的,即在繼承的一瞬間,基類大小變為0,而繼承它的類的大小只與自己的成員變數有關(此處預設為單一繼承):
可以看到,32位系統中,int
和float
佔4個位元組,所以最終類的例項大小為8。
可以看到,輸出還是8,即便加上了靜態成員變數。這是因為靜態成員變數其實存放的地方是在別的地方(全域性變數/靜態變數區,畢竟要讓所有例項可見),所以不會影響到例項的大小。
可以看到,函式不占用類的空間,這裡是1是因為編譯器分配了1個位元組來佔位。我們還可以驗證下:
於是,類的空間從1位元組變成了4位元組,不再是像空類那樣的1位元組了。
雖然char
只占用1個位元組,但是因為存在資料對齊,所以需要補齊到4的倍數(補齊char
到4位元組,為了方便cpu計算)。另外,這裡其實可以分化出另外幾個情況,例如連續兩個char
放在一起:
以及分開來放:
可以看到,順序對例項大小的影響。這是因為,如果兩個char
放在一起的話,那麼編譯器會將這兩個char
放在一起,然後補齊。如果不是連續放著的,那麼會分別補齊到4位元組。因此,盡量「湊」變數型別到4位元組,這樣可以讓補齊後的例項大小小一些。另外,要注意的是,含有陣列的時候是乙個個地連續地放,而不是視為整體,所以如果有陣列,例如:
再舉個例子:
class test8 ;
有陣列的時候,先連續擺放好,然後再補齊。
注意,上面說到的補齊到4位元組是因為類裡面最大的型別就是int
,是4個位元組,如果有更大的,那麼就要補齊到更大的位元組對應的倍數,如:
這裡出現了8位元組的double
,那麼補齊到8位元組。其實之所以補齊8位元組,是因為我是在windows平台下編譯的,如果是linux,即是用gcc,那麼其實還是當型別大小超過4位元組的時候,只要求起始位址是4的整數倍。
這部分理解要結合虛函式相關的知識。
class funconly2 ;
virtual ~funconly2() {};
private:
void boo() {};
};int main()
這裡因為多了個虛指標,所以大小為4,所以類大小要加上虛指標的4:
class funconly2 ;
virtual ~funconly2() {};
private:
void boo() {};
int br;
};
例如上面這樣的,就是int
的4加上虛指標的4。
大概總結下,類的大小需要考慮以下內容:
所有非靜態成員變數大小
資料對齊到多少位
有無虛函式(即需不需要指向虛函式表的指標,如果考慮繼承的情況,則還需要看繼承了多少個指向虛函式表的指標)
c++中空類佔一位元組原因詳解:建議看,對空白類的講解比較詳細
sizeof計算空間大小的總結
《c++ primer 第5版》
C 類的大小的計算
c 的類的大小現在經常出現在筆試題目當中。那我們先看看乙個例子 程式的輸出結果 sizeof a 1 sizeof b 1 sizeof c 4 sizeof d 8 為什麼會出現這種結果呢?初學者肯定會很煩惱是嗎?類a,b明明是空類,它的大小應該為為 為什麼 編譯器輸出的結果為 呢?這就是我們剛才...
C 類的大小計算
1.空類的大小 class c2 結果 sizeof c2 1 分析 這是因為當我們例項化乙個類物件時,就是為其分配記憶體空間,並且每乙個例項化的類都會有乙個獨一無二的記憶體位址,空類也不例外,必須為其分配乙個記憶體,因此編譯器給分配了乙個位元組的記憶體,使其獨一無二。2.只含有乙個虛函式的類的大小...
c 類大小計算
先給出總結 以下測試均在x64系統執行 1 原則1 空類的大小為1位元組。includeusing namespace std class a int main int main virtual void fun2 int test1 static void test2 static int c s...