一個類的實例化對象所佔空間的大小? 注意不要說類的大小,是類的對象的大小。 首先,類的大小是什麼?確切的說,類只是一個類型的定義,它是沒有大小可言的,用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個字節的內存空間。