類的大小

先看一個空的類佔多少空間?

 

  1. class Base  
  2. {  
  3. public:  
  4.     Base();  
  5.     ~Base();  
  6.   
  7. };  

 

    注意到我這裏顯示聲明瞭構造跟析構,但是sizeof(Base)的結果是1.

     因爲一個空類也要實例化,所謂類的實例化就是在內存中分配一塊地址,每個實例在內存中都有獨一無二的地址。同樣空類也會被實例化,所以編譯器會給空類隱含的添加一個字節,這樣空類實例化之後就有了獨一無二的地址了。所以空類的sizeof爲1。

   而析構函數,跟構造函數這些成員函數,是跟sizeof無關的,也不難理解因爲我們的sizeof是針對實例,而普通成員函數,是針對類體的,一個類的成員函數,多個實例也共用相同的函數指針,所以自然不能歸爲實例的大小,這在我的另一篇博文有提到。

   接着看下面一段代碼

  1. class Base  
  2. {  
  3. public:  
  4.     Base();                  
  5.     virtual ~Base();         //每個實例都有虛函數表  
  6.     void set_num(int num)    //普通成員函數,爲各實例公有,不歸入sizeof統計  
  7.     {  
  8.         a=num;  
  9.     }  
  10. private:  
  11.     int  a;                  //佔4字節  
  12.     char *p;                 //4字節指針  
  13. };  
  14.   
  15. class Derive:public Base  
  16. {  
  17. public:  
  18.     Derive():Base(){};       
  19.     ~Derive(){};  
  20. private:  
  21.     static int st;         //非實例獨佔  
  22.     int  d;                     //佔4字節  
  23.     char *p;                    //4字節指針  
  24.   
  25. };  
  26.   
  27. int main()   
  28. {   
  29.     cout<<sizeof(Base)<<endl;  
  30.     cout<<sizeof(Derive)<<endl;  
  31.     return 0;  
  32. }  

 

結果自然是

12

20

 

Base類裏的int  a;char *p;佔8個字節。

而虛析構函數virtual ~Base();的指針佔4子字節。

其他成員函數不歸入sizeof統計。

Derive類首先要具有Base類的部分,也就是佔12字節。

int  d;char *p;佔8字節

static int st;不歸入sizeof統計

所以一共是20字節。

 

在考慮在Derive里加一個成員char c;

  1. class Derive:public Base  
  2. {  
  3. public:  
  4.     Derive():Base(){};  
  5.     ~Derive(){};  
  6. private:  
  7.     static int st;  
  8.     int  d;  
  9.     char *p;  
  10.     char c;  
  11.   
  12. };  

這個時候,結果就變成了

12

24

 

一個char c;增加了4字節,說明類的大小也遵守類似class字節對齊,的補齊規則。

具體的可以看我那篇《5分鐘搞定字節對齊》

 

 

至此,我們可以歸納以下幾個原則:

1.類的大小爲類的非靜態成員數據的類型大小之和,也就是說靜態成員數據不作考慮。

2.普通成員函數與sizeof無關。

3.虛函數由於要維護在虛函數表,所以要佔據一個指針大小,也就是4字節。

4.類的總大小也遵守類似class字節對齊的,調整規則。





上一篇文章研究了關於類大小的4條規則後,我們再結合虛函數表,來研究下類的大小。

 

  1. class Base  
  2. {  
  3. public:  
  4.     Base(){};  
  5.     virtual ~Base(){};  
  6.     void set_num(int num)  
  7.     {  
  8.         a=num;  
  9.     }  
  10.     virtual int get_num()  
  11.     {  
  12.         return a;  
  13.     }  
  14. private:  
  15.     int  a;  
  16.     char *p;  
  17. };  
  18.   
  19. class Derive:public Base  
  20. {  
  21. public:  
  22.     Derive():Base(){};  
  23.     ~Derive(){};  
  24.          virtual int get_num()  
  25.     {  
  26.         return d;  
  27.     }  
  28. private:  
  29.     static int st;  
  30.          int  d;  
  31.          char *p;  
  32.     char c;  
  33.   
  34. };  
  35.   
  36. int main()   
  37. {   
  38.     cout<<sizeof(Base)<<endl;  
  39.     cout<<sizeof(Derive)<<endl;  
  40.     return 0;  
  41. }  

 

在Base類裏添加了virtual int get_num()函數,而子類也重新實現了virtual int get_num()函數。

但是結果依然是

12

24

 

說明子類只是共用父類的虛函數表,因此一旦父類裏有虛函數,子類的虛函數將不計入sizeof大小。

 

這可以認爲是一個補充規則。


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