類的大小可以歸納以下幾個原則:
1、類的大小爲類的非靜態成員數據的類型大小之和,也就是說靜態成員數據不作考慮。
2、類的大小與類中的構造函數、析構函數以及其他的普通成員函數無關(虛函數除外),只與它當中的成員數據有關。
3、虛函數由於要維護虛函數表,所以要佔據一個指針大小,也就是4字節。
4、爲了優化存取效率,類的總大小也遵守類似class字節對齊的(與基本數據類型中的長度最大的對齊)。
5、一個類裏若有虛函數,無論有多少個虛函數都只有一個指向虛表的指針。
6、子類只是共用父類的虛函數表,因此一旦父類裏有虛函數,子類的虛函數將不計入sizeof大小。
7、子類的大小裏包含有父類的私有成員大小。
7、如果該類是虛繼承的,則還會有一個指向父類的指針,該指針爲指向虛基類的指針(Pointer to virtual base class)。
8、空類佔用一個字節的空間。
一、簡單數據類的大小
示例1:
class A
{
};
說明:sizeof(A)=1。由於該類沒有定義數據成員,也就是說他沒有佔據存儲空間,但是由於當創建一個對象時,要標識一個對象,必須通過給它分配存儲空間來引用對象,兩者權衡之下,系統就給它分配了一個字節的存儲空間。
示例2:
class A
{
int a;
char b;
};
說明:sizeof(A)=8。int a佔用4個字節,char b佔用1個字節,但因爲要變量對齊,此例中與int對齊,所以變量b要佔用4個字節。
示例3:
class A
{
int a;
double c;
};
說明:sizeof(A)=16。double c佔用8個字節,int a佔用4個字節,但是因爲要與變量長度最大的對齊,此例中與double對齊,所以變量a要佔用8個字節。
示例4:
class A
{
int a;
char b;
double c;
};
說明:sizeof(A)=16。double c佔用8個字節,int a佔4個字節,char b佔1個字節,但是因爲要變量對齊,而且int a和 char b是連續的且總大小不大於要對齊的8字節,所以它們共用8字節的長度。
示例5:
class A
{
char a;
double c;
int b;
};
說明:sizeof(A)=24。char a和int b不是連續的,不能共用字節塊,要變量對齊,則各要佔用8字節的長度。
二、複雜類的大小
示例1:
class A
{
virtual func(){};
char a;
double c;
};
說明:sizeof(A)=24。因爲有虛函數,所以有指向虛函數表的指針,佔4個字節,但因爲要變量對齊,所以要佔8個字節的大小。注意,該指向虛函數表的指針與char a不是連續的,所以不能共用8個字節。
示例2:
class A
{
public:
A(){};
virtual ~A(){};
void set_num(int num)
{
a=num;
}
virtual int get_num()
{
return a;
}
private:
int a;
char *p;
};
說明:sizeof(A)=12。int a佔4個字節,char *p佔4個字節,因爲有虛函數,所以有指向虛函數表的指針,佔4個字節。
示例2:
class A
{
public:
virtual void aa(){};
private:
int a;
static int abc;
};
class B : public A
{
int b;
public:
virtual void bb(){};
};
class C : public virtual B
{
private:
int c;
};
class D : public virtual C
{
public:
virtual void dd(){};
private:
int d;
};
說明:sizeof(A)=8。int a佔4個字節;int abc是靜態變量,不佔類的空間;因爲是虛函數,會有一個指向虛函數表的指針,佔4個字節。
sizeof(B)=12。在A的大小基礎上增加了一個int b的變量,增加4字節。
sizeof(C)=20。因爲是虛繼承,所在多了一個指向虛基類的指針,佔4字節;多了一個int c的變量,佔4字節;所以在B的基礎上增加了8字節。
sizeof(D)=32。虛繼承,又多一個指向虛基類的指針,佔4字節;多一個int d的變量,佔4字節;