C++類的大小介紹
1、C++結構體和類的關系
為什麼講C++
類的大小要提到結構體呢,因為可能很多和我一樣的學子,接觸過C語言的結構體對齊,但不明白類的大小怎麼計算,這其中都要用到內存對齊的概念,對於內存對齊的概念之前已經說過瞭,可以參考這篇博客:結構體字節對齊和共用體大小 明白結構體的內存大小計算後,就要明白類和結構體的關系:
在C++中,結構體和類的唯一區別就是: 結構體和類具有不同的默認訪問控制屬性。
類中,對於未指定訪問控制屬性的成員,其訪問控制屬性為私有類型(private)。
結構體中,對於未指定任何訪問控制屬性的成員,其訪問控制屬性為公有類型(public)。
所以結構體的大小和類的大小是一樣的,在C++中,結構體也可以實現實現繼承和多態(可能很驚訝,可以去看看這篇博文:C++中結構體與類的區別,還要明確,靜態成員變量和成員函數所占用的空間肯定不是結構體或類的空間。還有就是空的類的大小是1字節,以方便類進行實例化。
代碼進行驗證:
#include <iostream> using namespace std; struct Node { }; class Test{ }; int main () { cout << "sizeof(struct Node) = " << sizeof(Node) << endl; cout << "sizeof(class Test) =" << sizeof(Test) << endl; system("pause"); return 0; }
代碼運行結果為:
2、繼承類的大小
繼承允許我們依據另一個類來定義一個類,會把一個類的成員大小都繼承下來,所以繼承瞭的派生類大小一定要考慮基類的大小,首先考慮的最大對齊數,派生類的最大對齊數要考慮基類的最大對齊數。
下面以實際代碼進行說明:
#include <iostream> using namespace std; class Base{ public: void func() { //成員函數不占用類的空間大小 } private: static int m_val1; // 靜態成員不占用類的空間 int m_valInt; char m_valChar; double m_valDouble; }; class Son:public Base{ public: static int func() { //靜態成員函數也不占用內存空間 return 0; } private: int m_sonValint; }; int main () { cout << "sizeof(Base) = " << sizeof(Base) << endl; cout << "sizeof(Son) = " << sizeof(Son) << endl; system("pause"); return 0; }
代碼運行結果為:
可以明確,靜態成員變量和成員函數所占用的空間類的空間,所以Base類的最大對齊數為double類型的大小(8字節),按照順序存儲,
Base類的大小計算應該為:
sizeof(Base)= 4 + 1 + 3(浪費) + 8 = 16字節
Son類繼承瞭Base類,它的最大對齊數也就是8字節,
所以Son類的大小計算應該為:
sizeof(Son) = 4 + 1 + 3(浪費) + 8 + 8 = 24字節
註意類的也要考慮存儲順序,如果把Base類中的m_valChar
放到m_valDouble
後面,
Base類的大小計算就變成瞭:
sizeof(Base)= 4 + 4(浪費)+ 8 + 1 + 7(浪費)= 24字節
Son類的大小就算就變成瞭:
sizeof(Son)= 4 + 4(浪費)+ 8 + 1 + 3(浪費) + 4= 24字節
由此可以推算出多繼承類的大小計算,菱形繼承也是一樣,都會繼承基類的內存,尤其註意虛繼承的情況,虛繼承隻是避免瞭菱形繼承出現的二義性,但不是不繼承,
如以下代碼:
#include <iostream> using namespace std; class Base{ public: void func() { //成員函數不占用類的空間大小 } public: double m_valDouble; }; class Son1:virtual public Base{}; //虛繼承 class Son2:virtual public Base{}; //虛繼承 class GrandSon:public Son1,public Son2{}; int main () { cout << "sizeof(GrandSon) = " << sizeof(GrandSon) << endl; GrandSon gs; // gs.m_valDouble = 10; //如果不是虛繼承就會出現二義性 system("pause"); return 0; }
代碼運行結果為:
上述GrandSon
的依舊為16字節,因為它從Son1繼承來瞭一份,又從Son2繼承來瞭一份,所以,虛繼承隻是避免瞭訪問的二義性,也可見菱形繼承會對內存空間造成浪費 。
3、多態類的大小
多態類唯一的區別就是計算類大小要考慮到虛寒表指針的大小,指針的大小和系統相關,32位機器為4字節,64位機器為8字節,指針的大小也要作為最大對齊數的考慮范圍。
代碼說明如下:
#include <iostream> using namespace std; class Base{ public: virtual void func() = 0; //純虛函數,會生成虛函數表指針 public: char m_valChar; }; class Son: public Base{ public: void func() {}; public: int m_SonvalInt; }; int main () { cout << "sizeof(Base) = " << sizeof(Base) << endl; cout << "sizeof(Son) = " << sizeof(Son) << endl; system("pause"); return 0; }
代碼運行結果為:
Base類的大小為8字節,是因為虛函數表指針占用瞭4字節,所以Base類的最大對齊數為4字節,虛函數表在構造函數的時候就會生成,所以,虛函數表指針肯定優先存儲,
所以Base類大小的計算為:
sizeof(Base) = 4 + 1 + 3(浪費) = 8字節
則Son類的大小計算為:
sizeof(Son)= 4 + 1 + 3(浪費) + 4 = 12字節
到此這篇關於C++類的大小介紹的文章就介紹到這瞭,更多相關C++類的大小內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!