C++技術——類記憶體空間
1.類本身是一個數據型別,在沒有定義物件前是不佔用記憶體空間的,定義物件的時候才會分
配空間,計算一個類的物件佔用多少空間用 sizeof(類名或物件)
2.類的物件大小是其資料成員(非靜態-資料段)和虛表大小的和.(虛擬函式:要佔用4個位元組,用來指定虛擬函式的虛擬函式表的入口地址。所以一個類的虛擬函式所佔用的地址是不變的,和虛擬函式的個數是沒有關係的)。
3.如果一個類中沒有資料成員,也沒有虛表那麼這個類的大小規定為 1 個位元組.
計算類記憶體空間大小需要考慮到地址對齊問題,相關知識如下:
最近在複習c++的一些基礎,感覺這篇文章很不錯,轉載來,大家看看!
類所佔記憶體的大小是由成員變數(靜態變數除外)決定的,成員函式(這是籠統的說,後面會細說)是不計算在內的。
摘抄部分:
成員函式還是以一般的函式一樣的存在。a.fun()是通過fun(a.this)來呼叫的。所謂成員函式只是在名義上是類裡的。其實成員函式的大小不在類的物件裡面,同一個類的多個物件共享函式程式碼。而我們訪問類的成員函式是通過類裡面的一個指標實現,而這個指標指向的是一個table,table裡面記錄的各個成員函式的地址(當然不同的編譯可能略有不同的實現)。所以我們訪問成員函式是間接獲得地址的。所以這樣也就增加了一定的時間開銷,這也就是為什麼我們提倡把一些簡短的,呼叫頻率高的函式宣告為inline形式(行內函數)。
(一)
class CBase
{
};
sizeof(CBase)=1;
為什麼空的什麼都沒有是1呢?
c++要求每個例項在記憶體中都有獨一無二的地址。//注意這句話!!!!!!!!!!
空類也會被例項化,所以編譯器會給空類隱含的新增一個位元組,這樣空類例項化之後就有了獨一無二的地址了。所以空類的sizeof為1。
(二)
class CBase
{
int a;
char p;
};
sizeof(CBase)=8;
記得對齊的問題。int 佔4位元組//注意這點和struct的對齊原則很像!!!!!
char佔一位元組,補齊3位元組
(三)
class CBase
{
public:
CBase(void);
virtual ~CBase(void);
private:
int a;
char *p;
};
再執行:sizeof(CBase)=12
C++ 類中有虛擬函式的時候有一個指向虛擬函式的指標(vptr),在32位系統分配指標大小為4位元組。無論多少個虛擬函式,只有這一個指標,4位元組。//注意一般的函式是沒有這個指標的,而且也不佔類的記憶體。
(四)
class CChild : public CBase
{
public:
CChild(void);
~CChild(void);
virtual void test();
private:
int b;
};
輸出:sizeof(CChild)=16;
可見子類的大小是本身成員變數的大小加上父類的大小。//其中有一部分是虛擬函式表的原因,一定要知道
父類子類共享一個虛擬函式指標
(五)
#include<iostream.h>
class a {};
class b{};
class c:public a{
virtual void fun()=0;
};
class d:public b,public c{};
int main()
{
cout<<"sizeof(a)"<<sizeof(a)<<endl;
cout<<"sizeof(b)"<<sizeof(b)<<endl;
cout<<"sizeof(c)"<<sizeof(c)<<endl;
cout<<"sizeof(d)"<<sizeof(d)<<endl;
return 0;}
程式執行的輸出結果為:
sizeof(a) =1
sizeof(b)=1
sizeof(c)=4
sizeof(d)=8
前三種情況比較常見,注意第四種情況。類d的大小更讓初學者疑惑吧,類d是由類b,c派生邇來的,它的大小應該為二者之和5,為什麼卻是8 呢?這是因為為了提高例項在記憶體中的存取效率.類的大小往往被調整到系統的整數倍.並採取就近的法則,裡哪個最近的倍數,就是該類的大小,所以類d的大小為8個位元組.
總結:
空的類是會佔用記憶體空間的,而且大小是1,原因是C++要求每個例項在記憶體中都有獨一無二的地址。
(一)類內部的成員變數:
- 普通的變數:是要佔用記憶體的,但是要注意對齊原則(這點和struct型別很相似)。
- static修飾的靜態變數:不佔用內容,原因是編譯器將其放在全域性變數區。
(二)類內部的成員函式:
- 普通函式:不佔用記憶體。
- 虛擬函式:要佔用4個位元組,用來指定虛擬函式的虛擬函式表的入口地址。所以一個類的虛擬函式所佔用的地址是不變的,和虛擬函式的個數是沒有關係的