2017-01-16 84 views
9

假設我有類無數據:基類內的派生類的大小

struct Empty { 
    /*some methods here*/ 
}; 

而派生類

struct Derived: Empty { 
    int a; 
    int b; 
    char c; 
    .... 
}__attribute__((packed));` 

空類的對象有派生類的大小= 1部分空通常有0尺寸。據我瞭解編譯器看到基地Empty類沒有數據,所以它可以優化空的大小的情況下,它是「內部」派生但它不需要由標準。

所以,問題是:

我可以採用某種確定在編譯時派生類的空白部分並沒有真正佔用內存。

據我所知,我可以做像sizeof(Derived) = sizeof(a) + sizeof(b) ...這樣的檢查但它太冗長了,有幾個類像Derived。有更優雅的解決方案嗎?

+0

爲什麼你想知道這一點?請注意,成員或基類可以佔用內存而不會增加派生類的佔用空間(通過使用填充的空間)。還要注意結構體上的'sizeof'可以小於或大於它的成員和基的'sizeof'之和。 – skyking

+0

我將使用這些派生類來表示一些網絡數據。所以所有這樣的派生類將具有壓縮屬性。另外,我將繼承一些模板類來實現好奇的循環模板模式。這樣所有派生類將具有一些通用功能。不過,我不希望這種繼承會影響Derived類的佈局。 –

回答

11

您可以使用std::is_empty,以確保你從繼承類是零大小:

static_assert(std::is_empty<Empty>{}); 

如果是,empty base optimizationguaranteed to take place for standard-layout classes


我知道我可以做什麼檢查像sizeof(Derived) = sizeof(a) + sizeof(b) ...但它是太冗長。有更優雅的解決方案嗎?

這不能正常工作,因爲您需要考慮填充和最終屬性,如packed

+0

謝謝。不知道這個優化是有保證的。 –

+0

該標準不保證此優化。儘管使用真實世界的編譯器,但它在實踐中很常見。 – Peter

+1

@Peter:[它保證*標準佈局*類](http://stackoverflow.com/questions/10788823/is-the-empty-base-class-optimization-now-a-mandatory-optimization-at -least換)。我會澄清我的答案。 –

3

您可以使用更多的 「老」(以前 C++ 11)宏 - offsetof

struct Empty {}; 
struct NonEmpty { 
    int a; 
}; 
struct Derived1: Empty { 
    int a; 
    int b; 
    char c; 
}; 
struct Derived2: NonEmpty { 
    int a; 
    int b; 
    char c; 
}; 
static_assert(offsetof(Derived1,a) == 0,""); 
static_assert(offsetof(Derived2,a) != 0,""); 

您可以使用此宏來檢查你的成員變量的順序也:

static_assert(offsetof(Derived,a) < offsetof(Derived,b),""); 
static_assert(offsetof(Derived,b) < offsetof(Derived,c),""); 

但是別忘了 - offsetof有​​相同的限制:

如果type不是標準佈局類型,行爲是未定義的。 如果成員是靜態成員或成員函數,則行爲未定義。