類對象所佔用的內存空間

  一個類的實例化對象所佔空間的大小? 注意不要說類的大小,是類的對象的大小。 首先,類的大小是什麼?確切的說,類只是一個類型的定義,它是沒有大小可言的,用sizeof運算符對一個類型名操做,獲得的是具備該類型實體的大小ios

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 };  8 
 9 int main() 10 { 11  A obj; 12     int nLen = sizeof(obj); 13     cout << nLen << endl; //sizeof(一個空類)爲何等於1?
14 
15     return 0; 16 }

能夠看到一個空類對象的大小1.函數

一個空類對象的大小是1,爲何不是0?優化

  初學者確定會很煩惱?類A明明是空類,它的大小應該爲0,爲何編譯器輸出的結果爲1呢?這就是實例化的緣由(空類一樣被實例化),每一個實例在內存中都有一個獨一無二的地址,爲了達到這個目的,編譯器每每會給一個空類隱含的加一個字節,這樣空類在實例化後在內存中獲得了獨一無二的地址,因此obj的大小是1.
spa

  

打斷點調試的時候,選中obj,而後按快捷鍵shift+F93d

能夠看到obj的地址是0x0019f77b;而後點擊vs菜單欄上的窗口----內存-----內存(1)指針

而後把obj的內存地址粘貼過來:調試

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     void func1() { };  9     void func2() { }; 10     void func3() { }; 11 }; 12 
13 int main() 14 { 15  A obj; 16     int nLen = sizeof(obj); 17     cout << nLen << endl; //sizeof(一個空類)爲何等於1?
18 
19     return 0; 20 }

此時給類A添加了三個成員函數,此時的類A對象的大小是多少呢?code

 

咱們看到此時類A對象obj的大小仍是1,說明類的成員函數不佔用類對象的內存空間對象

 

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     void func1() { };  9     void func2() { }; 10     void func3() { }; 11     char ab; 12 }; 13 
14 int main() 15 { 16  A obj; 17     int nLen = sizeof(obj); 18     cout << nLen << endl; // 19 
20     obj.ab = 'c'; 21     return 0; 22 }

咱們添加了類A的成員變量ab以後,類A對象的大小是多大呢?blog

咱們看到類A對象obj的大小是1.shift+F9咱們獲取到obj的內存地址

當斷點走過obj.ab = 'c'這條賦值語句以後

能夠看到原來0bj的內存地址上存儲了63這個十六進制,而十六進制63對應的ASCII碼恰好是字符c,因此說是一個字節大小。同時也說明了成員變量佔用類對象的內存空間

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     void func1() { };  9     void func2() { }; 10     void func3() { }; 11     //char ab;
12     int nab; 13 }; 14 
15 int main() 16 { 17  A obj; 18     int nLen = sizeof(obj); 19     cout << nLen << endl; //
20 
21     //obj.ab = 'c';
22     obj.nab = 12; 23     return 0; 24 }

輸出結果爲:

打斷點看到obj的內存地址是0x00cff9b4。而咱們能夠看到類A的成員變量是佔用了4個字節來存儲數據的。

 咱們再來看一個例子:

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A{};  6 class B{};  7 class C : public A  8 {  9     virtual void func() = 0; 10 }; 11 
12 class D : public B, public C 13 { 14 
15 }; 16 
17 int main() 18 { 19     cout << sizeof(A) << endl; 20     cout << sizeof(B) << endl; 21 
22     cout << sizeof(C) << endl; 23     cout << sizeof(D) << endl; 24 
25     return 0; 26 }

輸出結果爲:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class A{};
 6 class B1{};
 7 class B 
 8 {
 9     char c;
10 };
11 class C : public A 
12 {
13     virtual void func() = 0;
14 };
15 
16 class D : public B, public C {};
17 
18 class E :public B1, public C {};
19 int main()
20 {
21     cout << sizeof(A) << endl;
22     cout << sizeof(B) << endl;
23 
24     cout << sizeof(C) << endl;
25     cout << sizeof(D) << endl;
26     cout << sizeof(E) << endl;
27 
28     return 0;
29 }

輸出結果:

類A,B的大小爲1上面咱們已經講過緣由,而類C是由類A派生出來的,它裏面有一個純虛函數,因爲有虛函數的緣由,有一個指向虛函數的指針(vptr),在32位的系統分配給指針的大小爲4個字節,因此最後獲得類C的大小爲4個字節(類裏只要有一個虛函數,或者說至少有一個虛函數,這個類就會產生一個指向虛函數的指針,有兩個虛函數就會產生兩個指向虛函數的指針,類自己,指向虛函數的指針(一個或者一堆)要有地方存放,這些指針就存放在一個表格裏,這個表格咱們稱爲「虛函數表」,這個虛函數表是保存在可執行文件中的,在程序執行的時候載入到內存中來。無論有幾個虛函數,在32位的系統sizeof()都是多了4個字節)

類D的大小更讓初學者疑惑,類D是由類B,C派生而來的,它的大小應該爲兩者之和5,爲何是8呢?這是由於爲了提升實例在內存中的存取效率,類的大小每每被調整到系統的整數倍,並採起就近的法則,離哪一個最近的倍數,就是該類的大小,因此類D的大小爲8個字節。

下面咱們再看一個例子:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class A
 6 {
 7 private:
 8     int data;
 9 };
10 
11 class B
12 {
13 private:
14     int data;
15     static int xs;
16 };
17 int B::xs = 10;
18 int main()
19 {
20     cout << sizeof(A) << endl;
21     cout << sizeof(B) << endl;
22 
23     return 0;
24 }

輸出結果爲:

爲何類B比類A多了一個數據成員,大小卻和類A的大小相同呢?由於類B的靜態數據成員被編譯器放在程序的一個global data members中,它是類的一個數據成員,可是它不影響類的大小,無論這個類實際產生了多少實例,仍是派生了多少新的類,靜態成員在類中只有一個實體存在,而類的非靜態數據成員只有被實例化的時候,他們才存在,可是類的靜態數據成員一旦被聲明,不管類是否被實例化,它都已經存在,能夠這麼說,類的靜態數據成員是一種特殊的全局變量。

下面咱們看一個有構造函數,和析構函數的類的大小,它又是多大呢?

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     A(int a) { x = a; }  9     void func() 10  { 11         cout << x << endl; 12  } 13 
14     ~A() { } 15 private: 16     int x; 17     int g; 18 }; 19 
20 class B 21 { 22 public: 23 private: 24     int a; 25     int b; 26     static int xs; 27 }; 28 
29 int B::xs = 20; 30 
31 int main() 32 { 33     A a(10); 34     //a.func();
35 
36  B b; 37     cout << sizeof(a) << endl; 38     cout << sizeof(b) << endl; 39     return 0; 40 }

它們的結果均相同,能夠看出類的大小與它當中的構造函數,析構函數,以及其餘的成員函數無關,只與它當中的成員數據有關.

 

從以上幾個例子咱們能夠總結出來類的大小

1.爲類的非靜態成員數據的類型大小之和.
2.由編譯器額外加入的成員變量的大小,用來支持語言的某些特性(如:指向虛函數的指針). 
3.爲了優化存取效率,進行的邊緣調整(字節對齊). 
4 與類中的構造函數,析構函數以及其餘的成員函數無關.

另外:一個類對象至少佔用1個字節的內存空間。

相關文章
相關標籤/搜索