C++類佔內存大小

 

總結:空類佔用1個字節,非空類的大小=非靜態成員變量佔用大小(靜態變量不佔內存)+虛函數佔用內存(4字節,不管有多少個虛函數)+字節對齊的開銷(成員函數不算入類的空間),子類大小=本身成員變量大小+父類大小

來看一個總的例子:

#include<stdio.h>
class Car
{	
public:
	Car(void){};	
	 ~Car(void){};	
public:	
	int a;
	char b;
	char* c;
	static int d;
	void Fun(){};
	void Fun1()
	{
		int a1;
		long a2;
	};
	virtual Fun3(){};
	virtual Fun4(){};
	
};
void main()
{	
	int size = 0;	
	Car objCar;	
	size = sizeof(objCar);	
	printf("%s %d /r", "Class Car Size:", size);
}

輸出結果:16

其中int a佔4個字節,char b佔一個字節,char * c佔4個字節,static int d不佔空間,void Fun成員函數不佔空間,void Fun1裏面定義了兩個變量也不佔空間,Fun3跟Fun4只佔4個字節(指針所佔空間,具體見下文分析)。

4+1+3(字節對齊)+4+4=16


 

以下引用:http://blog.csdn.net/yzx0803060320/article/details/7302130

先看這麼個問題——已知:

class CBase
{
int a;
char *p;
};

那麼運行cout<<"sizeof(CBase)="<<sizeof(CBase)<<endl;之後輸出什麼?

這個應該很簡單,兩個成員變量所佔的大小有嘛——8。可由時候人就是愛犯這個錯誤:這麼簡單的問題人家會問你?再想想……好像C++類裏面有個什麼 函數指針,也應該佔字節吧!?什麼指針來着?忘了(還是水平低不紮實)!流汗中……算了姑且認爲是構造函數和析構函數吧。一人一個加上剛纔那8個16個。 好笑嗎?這是我犯的錯誤!!!到底C++類的sizeof是多少呢?沒有所謂的函數指針問題嗎?不甘心,編個例子看看:

第一步:給丫來個空的(不好意思上火粗魯了)

class CBase
{
};

運行cout<<"sizeof(CBase)="<<sizeof(CBase)<<endl;

sizeof(CBase)=1;

爲什麼空的什麼都沒有是1呢?查資料……查啊查……OK這裏了:先了解一個概念:類的實例化,所謂類的實例化就是在內存中分配一塊地址,每個實例在內存中都有獨一無二的地址。同樣空類也會被實例化(別拿豆包不當乾糧,空類也是類啊),所以編譯器會給空類隱含的添加一個字節,這樣空類實例化之後就有了 獨一無二的地址了。所以空類的sizeof爲1。繼續下一步:

第二步:

還是最初的那個類,運行結果:sizeof(CBase)=8

沒什麼說的,兩個內部變量的大小。難道我記錯了沒有什麼指針問題的存在?再試試(早這麼有求知慾也不會丟人了,這回來勁了)

第三步:添個虛函數

class CBase
{
public :
CBase(
void );
virtual ~CBase(void );
private :
int a;
char *p;
};

再運行:sizeof(CBase)=12

嗨!問題出來了!!跟虛函數有關。爲什麼呢?查資料ing……

有了:“C++ 類中有虛函數的時候有一個指向虛函數的指針(vptr),在32位系統分配指針大小爲4字節”噢原來如此害死我了。那麼繼承類呢?

第四步:

基類就是上面的了不寫了

class CChild :
public CBase
{
public :
CChild(
void );
~ CChild(void);
private :
int b;
};

運行:cout<<"sizeof(CChild)="<<sizeof(CChild)<<endl;

輸出:sizeof(CChild)=16;

可見子類的大小是本身成員變量的大小加上父類的大小

關於虛擬繼承(相當於添加了一個接口):

class COneMember

{

public:

COneMember(int iValue = 0){m_iOne = iValue;};

private:

int m_iOne;

};

class CTwoMember:virtual public COneMember

{

private:

int m_iTwo;

};

長度:12

內存結構:

E8 2F 42 00 //指針,指向一個關於偏移量的數組,且稱之虛基類偏移量表指針

CC CC CC CC // m_iTwo

00 00 00 00 // m_iOne(虛基類數據成員)

評註:virtual 讓長度增加了4 ,其實是多了一個指針,關於這個指針,確實有些複雜,別的文章有具體分析,這裏就不岔開具體講了,可認爲它指向一個關於虛基類偏移量的數組,偏移量是關於虛基類數據成員的偏移量。
關於閉合繼承

class ClassA

{

public:

ClassA(int iValue=1){m_iA = iValue;};

private:

int m_iA;

};

class ClassB:public ClassA

{

public:

ClassB(int iValue=2){m_iB = iValue;};

private:

int m_iB;

};

class ClassC: public ClassC

{

public:

ClassC(int iValue=3){m_iC = iValue;};

private:

int m_iC;

};

class CComplex :public ClassB, public ClassC

{

public:

CComplex(int iValue=4){m_iComplex = iValue;};

private:

int m_iComplex;

};

長度:24

內存結構:

14 30 42 00 //ClassB的虛基類偏移量表指針

02 00 00 00 //m_iB

C4 2F 42 00 //ClassC的虛基類偏移量表指針

03 00 00 00 //m_iC

04 00 00 00 //m_iComplex

01 00 00 00 //m_iA

評註:和預料中的一樣,虛基類的成員m_iA 只出現了一次,而且是在最後邊。當然了,更復雜的情況要比這個難分析得多,但虛繼承不是我們研究的重點,我們只需要知道:虛繼承利用一個“虛基類偏移量表指針”來使得虛基類即使被重複繼承也只會出現一次。
看一下關於static成員

class CStaticNull

{

public:

CStaticNull(){printf("Construct\n");}

~CStaticNull(){printf("Desctruct\n");}

static void Foo(){printf("Foo\n");}

static int m_iValue;

};

長度:1

內存結構:(同CNull2

評註:可見static 成員不會佔用類的大小static成員的存在區域爲靜態區,可認爲它們是“全局”的,只是不提供全局的訪問而已,這跟Cstatic 其實沒什麼區別。
帶有虛函數的類:

class CVirtualNull

{

public:

CVirtualNull(){printf("Construct\n");}

~CVirtualNull(){printf("Desctruct\n");}

virtual void Foo(){printf("Foo\n");} //或者是virtual void Foo()=0;都是佔4個字節大小

};

長度:4

內存結構:

00 31 42 00 //指向虛函數表的指針(虛函數表後面簡稱“虛表”)

00423100:(虛表)

41 10 40 00 //指向虛函數Foo 的指針

00401041:

E9 78 02 00 00 E9 C3 03 // 函數Foo 的內容(看不懂)

評註:帶虛函數的類長度就增加了4 ,這個4 其實就是個指針,指向虛函數表的指針,上面這個例子中虛表只有一個函數指針,值就是“0x00401041 ”,指向的這個地址就是函數的入口了。

子類有新的虛函數:

class CVirtualDerived: public CVirtualNull

{

public:

CVirtualDerived(){m_iVD=0xFF;};

~CVirtualDerived(){};

virtual void Foo2(){printf("Foo2\n");};

private:

int m_iVD;

};

長度:8

內存結構:

24 61 42 00 //虛表指針

FF 00 00 00 //m_iVD

00426124:(虛表)

23 10 40 00

50 10 40 00

評註:虛表還是隻有一張,不會因爲增加了新的虛函數而多出另一張來,新的虛函數的指針將添加在複製了的虛表的後面。

注意:當空類多繼承空類時,一個空類佔一個字節,一個空類繼承一個空類還是佔一個字節,一個空類繼承兩個空類時還佔一個字節;一個空類繼承N(N>2)個空類時,佔N-1個字節。不知道爲什麼,誰知道告訴我


發佈了8 篇原創文章 · 獲贊 9 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章