C++類的大小介紹
1、C++結(jié)構(gòu)體和類的關(guān)系
為什么講C++
類的大小要提到結(jié)構(gòu)體呢,因為可能很多和我一樣的學(xué)子,接觸過C語言的結(jié)構(gòu)體對齊,但不明白類的大小怎么計算,這其中都要用到內(nèi)存對齊的概念,對于內(nèi)存對齊的概念之前已經(jīng)說過了,可以參考這篇博客:C++結(jié)構(gòu)體字節(jié)對齊和共用體大小 明白結(jié)構(gòu)體的內(nèi)存大小計算后,就要明白類和結(jié)構(gòu)體的關(guān)系:
在C++中,結(jié)構(gòu)體和類的唯一區(qū)別就是: 結(jié)構(gòu)體和類具有不同的默認(rèn)訪問控制屬性。
類中,對于未指定訪問控制屬性的成員,其訪問控制屬性為私有類型(private
)。
結(jié)構(gòu)體中,對于未指定任何訪問控制屬性的成員,其訪問控制屬性為公有類型(public
)。
所以結(jié)構(gòu)體的大小和類的大小是一樣的,在C++中,結(jié)構(gòu)體也可以實(shí)現(xiàn)實(shí)現(xiàn)繼承和多態(tài)(可能很驚訝,可以去看看這篇博文:C++結(jié)構(gòu)體與類的區(qū)別詳情,還要明確,靜態(tài)成員變量和成員函數(shù)所占用的空間肯定不是結(jié)構(gòu)體或類的空間。還有就是空的類的大小是1字節(jié),以方便類進(jìn)行實(shí)例化。
代碼進(jìn)行驗證:
#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; }
代碼運(yùn)行結(jié)果為:
2、繼承類的大小
繼承允許我們依據(jù)另一個類來定義一個類,會把一個類的成員大小都繼承下來,所以繼承了的派生類大小一定要考慮基類的大小,首先考慮的最大對齊數(shù),派生類的最大對齊數(shù)要考慮基類的最大對齊數(shù)。
下面以實(shí)際代碼進(jìn)行說明:
#include <iostream> using namespace std; class Base{ public: void func() { //成員函數(shù)不占用類的空間大小 } private: static int m_val1; // 靜態(tài)成員不占用類的空間 int m_valInt; char m_valChar; double m_valDouble; }; class Son:public Base{ public: static int func() { //靜態(tài)成員函數(shù)也不占用內(nèi)存空間 return 0; } private: int m_sonValint; }; int main () { cout << "sizeof(Base) = " << sizeof(Base) << endl; cout << "sizeof(Son) = " << sizeof(Son) << endl; system("pause"); return 0; }
代碼運(yùn)行結(jié)果為:
可以明確,靜態(tài)成員變量和成員函數(shù)所占用的空間類的空間,所以Base類的最大對齊數(shù)為double類型的大?。?字節(jié)),按照順序存儲,
Base類的大小計算應(yīng)該為:
sizeof(Base)= 4 + 1 + 3(浪費(fèi)) + 8 = 16字節(jié)
Son類繼承了Base類,它的最大對齊數(shù)也就是8字節(jié),
所以Son類的大小計算應(yīng)該為:
sizeof(Son) = 4 + 1 + 3(浪費(fèi)) + 8 + 8 = 24字節(jié)
注意類的也要考慮存儲順序,如果把Base類中的m_valChar
放到m_valDouble
后面,
Base類的大小計算就變成了:
sizeof(Base)= 4 + 4(浪費(fèi))+ 8 + 1 + 7(浪費(fèi))= 24字節(jié)
Son類的大小就算就變成了:
sizeof(Son)= 4 + 4(浪費(fèi))+ 8 + 1 + 3(浪費(fèi)) + 4= 24字節(jié)
由此可以推算出多繼承類的大小計算,菱形繼承也是一樣,都會繼承基類的內(nèi)存,尤其注意虛繼承的情況,虛繼承只是避免了菱形繼承出現(xiàn)的二義性,但不是不繼承,
如以下代碼:
#include <iostream> using namespace std; class Base{ public: void func() { //成員函數(shù)不占用類的空間大小 } 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; //如果不是虛繼承就會出現(xiàn)二義性 system("pause"); return 0; }
代碼運(yùn)行結(jié)果為:
上述GrandSon
的依舊為16字節(jié),因為它從Son1繼承來了一份,又從Son2繼承來了一份,所以,虛繼承只是避免了訪問的二義性,也可見菱形繼承會對內(nèi)存空間造成浪費(fèi) 。
3、多態(tài)類的大小
多態(tài)類唯一的區(qū)別就是計算類大小要考慮到虛寒表指針的大小,指針的大小和系統(tǒng)相關(guān),32位機(jī)器為4字節(jié),64位機(jī)器為8字節(jié),指針的大小也要作為最大對齊數(shù)的考慮范圍。
代碼說明如下:
#include <iostream> using namespace std; class Base{ public: virtual void func() = 0; //純虛函數(shù),會生成虛函數(shù)表指針 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; }
代碼運(yùn)行結(jié)果為:
Base類的大小為8字節(jié),是因為虛函數(shù)表指針占用了4字節(jié),所以Base類的最大對齊數(shù)為4字節(jié),虛函數(shù)表在構(gòu)造函數(shù)的時候就會生成,所以,虛函數(shù)表指針肯定優(yōu)先存儲,
所以Base類大小的計算為:
sizeof(Base) = 4 + 1 + 3(浪費(fèi)) = 8字節(jié)
則Son類的大小計算為:
sizeof(Son)= 4 + 1 + 3(浪費(fèi)) + 4 = 12字節(jié)
到此這篇關(guān)于C++類的大小介紹的文章就介紹到這了,更多相關(guān)C++類的大小內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++?拷貝構(gòu)造函數(shù)與賦值的區(qū)別
拷貝構(gòu)造函數(shù)和賦值函數(shù)非常容易混淆,本文主要介紹了C++?拷貝構(gòu)造函數(shù)與賦值的區(qū)別,具有一定的參考價值,感興趣的可以了解一下2024-04-04C++將二叉樹轉(zhuǎn)為雙向鏈表及判斷兩個鏈表是否相交
這篇文章主要介紹了C++將二叉樹轉(zhuǎn)為雙向鏈表及判斷兩個鏈表是否相交的方法,文中還給出了求兩個鏈表相交的第一個節(jié)點(diǎn)列的實(shí)現(xiàn)方法,需要的朋友可以參考下2016-02-02C++中如何將operator==定義為類的成員函數(shù)
這篇文章主要介紹了C++中如何將operator==定義為類的成員函數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01c++ chrono 獲取當(dāng)前時間的實(shí)現(xiàn)代碼
這篇文章主要介紹了c++ chrono 獲取當(dāng)前時間的實(shí)現(xiàn)代碼,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07C++11的future和promise、parkged_task使用
這篇文章主要介紹了C++11的future和promise、parkged_task使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04C++?JSON庫?nlohmann::basic_json::array?的用法示例詳解
nlohmann::json是一個C++的JSON庫,它提供了一種容易和直觀的方法來處理JSON數(shù)據(jù),nlohmann::json::array()是用來創(chuàng)建一個JSON數(shù)組的方法,這篇文章主要介紹了C++ JSON庫nlohmann::basic_json::array的用法,需要的朋友可以參考下2023-06-06C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷
這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷的相關(guān)資料,需要的朋友可以參考下2017-06-06