2017-01-16 132 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不是标准布局类型,行为是未定义的。 如果成员是静态成员或成员函数,则行为未定义。