1. 程式人生 > >C++一個類對象的大小計算

C++一個類對象的大小計算

繼承 註意 inf base ++ 分享圖片 com 補齊 重寫

計算一個類對象的大小時的規律:

 1、空類、單一繼承的空類、多重繼承的空類所占空間大小為:1(字節,下同);

2、一個類中,虛函數本身、成員函數(包括靜態與非靜態)和靜態數據成員都是不占用類對象的存儲空間的;

3、因此一個對象的大小≥所有非靜態成員大小的總和(包括動態分配的變量...);

4、當類中聲明了虛函數(不管是1個還是多個),那麽在實例化對象時,編譯器會自動在對象裏安插一個指針vPtr指向虛函數表VTable;

5、虛繼承的情況:虛繼承的實現是通過一個虛基類指針列表;由於涉及到虛函數表和虛基表,會同時增加一個(多重虛繼承下對應多個)vfPtr指針指向虛函數表vfTable和一個vbPtr指針指向虛基表vbTable,這兩者所占的空間大 小為:8(或8乘以多繼承時父類的個數);

6、在考慮以上內容所占空間的大小時,還要註意編譯器下的“補齊”padding的影響,即編譯器會插入多余的字節補齊;

7、類對象的大小=各非靜態數據成員(包括父類的非靜態數據成員但都不包括所有的成員函數)的總和+ vfptr指針(多繼承下可能不止一個)+vbptr指針(多繼承下可能不止一個)+編譯器額外增加的字節。

非虛單繼承實例如下:

class A

{

char k[3];

public:

virtual void aa()

{

};

};

class B:public A

{

char j[3];

public:

virtual void bb()

{

};

};

class C:public B

{

char i[3];

public:

virtual void cc()

{

};

};

技術分享圖片

//一個字節 按4字節對齊

技術分享圖片

技術分享圖片

4(指向虛函數的虛指針)+4(自己的數據成員) = 8

4(指向虛函數的虛指針)+4(自己的數據成員)+4(父類A的數據成員)=12

4(指向虛函數的虛指針)+4(自己的數據成員)+8(父類的數據成員)=16

非虛多繼承實例如下:

技術分享圖片

技術分享圖片

重寫函數f()

Base -->char 類型

Base1:4(指向虛函數的虛指針)+4(自己的數據成員) = 8

Base2:4(指向虛函數的虛指針)+4(自己的數據成員) = 8

Base3:4(指向虛函數的虛指針)+4(自己的數據成員) = 8

Derive: 4(Base1指向虛函數表的虛指針)+4(Base1繼承的成員變量)+4(Base2指向虛函數表的虛指針)+4(Base2繼承的成員變量)+3(Base1指向虛函數表的虛指針)+4(Base3繼承的成員變量)+4(自己的數據成員)=28

1)虛函數表在最前面的位置。

2)成員變量根據其繼承和聲明順序依次放在後面。

3)每個父類都有自己的虛表。

4)子類的成員函數被放到了第一個父類的表中。

5)內存布局中,其父類布局依次按聲明順序排列。

6)每個父類的虛表中的f()函數都被overwrite成了子類的f()。這樣做就是為了解決不同的父類類型的指針指向同一個子類實例,而能夠調用到實際的函數。

非虛繼承的鉆石繼承:

技術分享圖片

技術分享圖片

紅色的部分就是重復的部分,就會造成二義性

虛繼承的鉆石繼承:

技術分享圖片

技術分享圖片

可以看出,少了重合的部分。但是,代價是增加了一個虛基類指針vbptr。

C++一個類對象的大小計算