sizeof()計算一個類的對象大小和sizeof(string)的問題

http://blog.csdn.net/vangoals/article/details/4264512

關於類的大小sizeof()的計算

首先,來看看一個只有構造函數和析構函數的空類:

  1. #include <iostream>  
  2. using namespace std;  
  3. class Base  
  4. {  
  5. public:  
  6.     Base();  
  7.     ~Base();  
  8. };  
  9. int main(int argc, char *argv[])  
  10. {  
  11.     cout << sizeof(Base) << endl;  
  12. }  

輸出結果爲:1

      因爲一個空類也要實例化,所謂類的實例化就是在內存中分配一塊地址,每個實例在內存中都有獨一無二的地址。同樣空類也會被實例化,所以編譯器會給空類隱含的添加一個字節,這樣空類實例化之後就有了獨一無二的地址了。所以空類的sizeof爲1。 而析構函數,跟構造函數這些成員函數,是跟sizeof無關的,也不難理解因爲我們的sizeof是針對實例,而普通成員函數,是針對類體的,一個類的成員函數,多個實例也共用相同的函數指針,所以自然不能歸爲實例的大小。

     如果給這個類添加成員變量,最後輸出的大小就是這些成員變量的大小之和(這裏涉及到一個成員對齊問題,不再敘述了)。

接下來再來看一個有繼承的例子:

  1. #include <iostream>  
  2. using namespace std;  
  3. class Base  
  4. {  
  5. public:  
  6.     Base();                  
  7.     ~Base();           
  8.     void set_num(int num)    //普通成員函數  
  9.     {  
  10.         a=num;  
  11.     }  
  12. private:  
  13.     int  a;                  //佔4字節  
  14.     char *p;                 //4字節指針  
  15. };  
  16. class Derive:public Base  
  17. {  
  18. public:  
  19.     Derive():Base(){};       
  20.     ~Derive(){};  
  21. private:  
  22.     static int st;         //非實例獨佔  
  23.         int  d;                //佔4字節  
  24. };  
  25. int main(int argc, char *argv[])   
  26. {   
  27.     cout<<sizeof(Base)<<endl;  
  28.     cout<<sizeof(Derive)<<endl;  
  29.     return 0;  
  30. }  

輸出結果爲:8   12

結果很顯然, Base 類按4字節對齊,所以是8個字節,Derive 類中不但繼承了Base 類的兩個成員變量,還多了兩個成員變量,但大小卻只有12字節,可以得出:靜態變量在計算時是不做考慮的。

上面的例子中都沒有涉及到虛函數,下面看個有虛函數的例子:

  1. #include <iostream>  
  2. using namespace std;  
  3. class Base  
  4. {  
  5. public:  
  6.     Base() {}  
  7.     virtual ~Base() {}  
  8. };  
  9. int main(int argc, char *argv[])  
  10. {  
  11.     cout << sizeof(Base) << endl;  
  12.     return 0;  
  13. }  

輸出結果爲:4

      和第一個程序相比,這個類中,析構函數變成了虛函數,類的大小也變成了4字節,這是因爲有了虛函數,編譯器就會爲類創建一個虛函數表(vtable),並創建一個指針(vptr)指向這個虛函數表。所以類大小變爲4字節。如果在 Base 類中再添加新的虛函數,該類的大小還是不會變,因爲指向虛函數的指針是放在虛函數表中的,指向虛函數表的指針不會變。

如果在這個類中添加數據成員,就會在4字節的基礎上對象大小。

下面再來看看虛函數的繼承問題:

  1. #include <iostream>  
  2. using namespace std;  
  3. class Base  
  4. {  
  5. public:  
  6.     Base();                  
  7.     virtual ~Base();           
  8.     void set_num(int num)    //普通成員函數  
  9.     {  
  10.         a=num;  
  11.     }  
  12. private:  
  13.     int  a;                  //佔4字節  
  14.     char *p;                 //4字節指針  
  15. };  
  16. class Derive:public Base  
  17. {  
  18. public:  
  19.     Derive():Base(){};       
  20.     ~Derive(){};  
  21.     virtual void foo() { }  
  22. private:  
  23.     static int st;         //非實例獨佔  
  24.         int  d;                //佔4字節  
  25. };  
  26. int main(int argc, char *argv[])   
  27. {   
  28.     cout<<sizeof(Base)<<endl;  
  29.     cout<<sizeof(Derive)<<endl;  
  30.     return 0;  
  31. }  

輸出結果爲:12    16

      Base類的大小爲12字節很顯然,Derive 類中,雖然有一個虛函數 foo ,但是因爲它是從Base 類繼承的,所以也繼承了其虛函數表,並沒有創新新的虛函數表,只是在繼承下來的表中添加了一項,所以大小爲16字節。

再來看看一個虛繼承的例子:

  1. #include <iostream>  
  2. using namespace std;  
  3. class Base  
  4. {  
  5. public:  
  6.     Base();                  
  7.     virtual ~Base();           
  8.     void set_num(int num)    //普通成員函數  
  9.     {  
  10.         a=num;  
  11.     }  
  12. private:  
  13.     int  a;                  //佔4字節  
  14.     char *p;                 //4字節指針  
  15. };  
  16. class Derive:virtual public Base  
  17. {  
  18. public:  
  19.     Derive():Base(){};       
  20.     ~Derive(){};  
  21.     virtual void foo() { }  
  22. private:  
  23.     static int st;         //非實例獨佔  
  24.         int  d;                //佔4字節  
  25. };  
  26. int main(int argc, char *argv[])   
  27. {   
  28.     cout<<sizeof(Base)<<endl;  
  29.     cout<<sizeof(Derive)<<endl;  
  30.     return 0;  
  31. }  

輸出結果爲:12    20

      這裏由於虛繼承而引入了一個間接的指針(vbc),該指針是指向虛函數表的一個slot,表中存放着該slot中存放虛基類子對象的偏移量的負值。所以大小比之前多了4字節。就算同時虛繼承自兩個類,也只會有一個這樣的間接指針,也就是大小也只多4字節。

說到這裏,關於類對象大小問題的計算應該差不多了。




關於string的大小sizeof()的計算。

string 內部的實現是保存一個指針,sizeof(string)等同與sizeof(char *),所以sizeof(string)的大小如果是32位平臺的話是4.

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