2016-05-15 30 views
2

有人可以幫助我瞭解sizeof()運算符的行爲嗎?爲什麼我的班級規模大於其會員總數?

#include <iostream> 

using namespace std; 

class A{ 
    int first; 
    double last; 
    public: 
    A(int a) 
    { 
     cout << a << endl; 
    } 
}; 
int main() 
{ 
    A a(3); 
    cout << sizeof(a) << endl; 
    return 0; 
} 

此代碼打印出我的大小爲16個字節。類的大小根據其成員計算。所以我有4個字節(int)+8字節(double)= 12。

那麼爲什麼我得到16個字節?

當我註釋掉intdouble成員時,我得到1個字節。

+0

如果您使用Visual C++,請參閱https://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx並嘗試使用'/ Zp1'選項使輸出爲12. –

+0

不,我使用普通的g ++編譯器 –

+0

GCC與Visual C++一樣「普通」:)在任何情況下,每個C++編譯器都提供類似的選項。這些東西本質上是特定於實現的。 –

回答

1

編譯器,勾畫出速度和其他因素,不一定適合節省空間類內部,所以接下來的裝修元素之前,它可能會留下大小4元后面的空4字節的塊。這使得現代架構(基於64位= 8字節)更快地訪問下一個元素。

另外,請注意,類對象的sizeof可能包含其他您不知道的數據,如指向虛擬函數表的指針等,這是編譯器的工作,代碼正確且快速地運行。

+0

這大部分都是正確的,除了編譯器設計類的方式不一定是針對速度優化的。其他因素也被考慮在內。特別是,如果一個平臺具有其他編譯器使用的不理想的ABI,則新編譯器可能最終會使用該ABI來兼容,即使它們可以通過降低兼容性來提供更快的ABI。 – hvd

+0

我認爲虛函數表被保存爲整個類的屬性,而不是類的每個實例。 –

1

只要POD類與C結構兼容,類中字段的佈局就是實現定義的。然而,即使在C結構實現中,由於各種原因(如性能)添加了填充。因此,您的編譯器可能會在int字段後面添加四個填充字節,以使double字段以8字節對齊的地址開始。

如果您沒有特別需要這樣做,可以通過多種方法來控制類/結構的對齊和填充,這些對齊和填充在編譯器中各不相同。例如,GCC的語法類似於__attribute__((packed)),它將刪除該填充。這很少需要 - 主要是當結構需要映射到設備寄存器時 - 並且通常會傷害性能,所以如果可能的話避免它。

0

編譯器將成員包裝到類中的默認方式是嘗試對齊字邊界,即字的大小的倍數(64位計算機上的8字節)。要停止包裝使用#pragma pack(1)或編譯器選項/Zp。這迫使編譯器將成員壓在一起。

一個類不允許具有零大小,因爲這可能意味着指向兩個不同對象的指針是相同的,所以它的最小大小爲1個字節。

+0

是的,謝謝。這說得通。 –

相關問題