C++類的大小介紹
1、C++結(jié)構(gòu)體和類的關(guān)系
為什么講C++類的大小要提到結(jié)構(gòu)體呢,因?yàn)榭赡芎芏嗪臀乙粯拥膶W(xué)子,接觸過C語言的結(jié)構(gòu)體對齊,但不明白類的大小怎么計(jì)算,這其中都要用到內(nèi)存對齊的概念,對于內(nèi)存對齊的概念之前已經(jīng)說過了,可以參考這篇博客:C++結(jié)構(gòu)體字節(jié)對齊和共用體大小 明白結(jié)構(gòu)體的內(nèi)存大小計(jì)算后,就要明白類和結(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)行驗(yà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ù)另一個(gè)類來定義一個(gè)類,會把一個(gè)類的成員大小都繼承下來,所以繼承了的派生類大小一定要考慮基類的大小,首先考慮的最大對齊數(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類的大小計(jì)算應(yīng)該為:
sizeof(Base)= 4 + 1 + 3(浪費(fèi)) + 8 = 16字節(jié)
Son類繼承了Base類,它的最大對齊數(shù)也就是8字節(jié),
所以Son類的大小計(jì)算應(yīng)該為:
sizeof(Son) = 4 + 1 + 3(浪費(fèi)) + 8 + 8 = 24字節(jié)
注意類的也要考慮存儲順序,如果把Base類中的m_valChar放到m_valDouble后面,
Base類的大小計(jì)算就變成了:
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é)
由此可以推算出多繼承類的大小計(jì)算,菱形繼承也是一樣,都會繼承基類的內(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é),因?yàn)樗鼜腟on1繼承來了一份,又從Son2繼承來了一份,所以,虛繼承只是避免了訪問的二義性,也可見菱形繼承會對內(nèi)存空間造成浪費(fèi) 。
3、多態(tài)類的大小
多態(tài)類唯一的區(qū)別就是計(jì)算類大小要考慮到虛寒表指針的大小,指針的大小和系統(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é),是因?yàn)樘摵瘮?shù)表指針占用了4字節(jié),所以Base類的最大對齊數(shù)為4字節(jié),虛函數(shù)表在構(gòu)造函數(shù)的時(shí)候就會生成,所以,虛函數(shù)表指針肯定優(yōu)先存儲,
所以Base類大小的計(jì)算為:
sizeof(Base) = 4 + 1 + 3(浪費(fèi)) = 8字節(jié)
則Son類的大小計(jì)算為:
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ū)別,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04
C++將二叉樹轉(zhuǎn)為雙向鏈表及判斷兩個(gè)鏈表是否相交
這篇文章主要介紹了C++將二叉樹轉(zhuǎn)為雙向鏈表及判斷兩個(gè)鏈表是否相交的方法,文中還給出了求兩個(gè)鏈表相交的第一個(gè)節(jié)點(diǎn)列的實(shí)現(xiàn)方法,需要的朋友可以參考下2016-02-02
C++中如何將operator==定義為類的成員函數(shù)
這篇文章主要介紹了C++中如何將operator==定義為類的成員函數(shù),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
c++ chrono 獲取當(dāng)前時(shí)間的實(shí)現(xiàn)代碼
這篇文章主要介紹了c++ chrono 獲取當(dāng)前時(shí)間的實(shí)現(xiàn)代碼,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
C++11的future和promise、parkged_task使用
這篇文章主要介紹了C++11的future和promise、parkged_task使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
C++?JSON庫?nlohmann::basic_json::array?的用法示例詳解
nlohmann::json是一個(gè)C++的JSON庫,它提供了一種容易和直觀的方法來處理JSON數(shù)據(jù),nlohmann::json::array()是用來創(chuàng)建一個(gè)JSON數(shù)組的方法,這篇文章主要介紹了C++ JSON庫nlohmann::basic_json::array的用法,需要的朋友可以參考下2023-06-06
C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷
這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷的相關(guān)資料,需要的朋友可以參考下2017-06-06

