零大小的结构

时间:2011-10-24 20:20:52

标签: c++

根据C ++标准(继承自C),空结构仍然具有非零大小。这个(可怜的恕我直言)的原因是两个不同的变量应该有不同的地址。现在,继承一个空结构并不总是“膨胀”该对象。但在某些情况下情况确实如此。

我有一个相当复杂的类架构,涉及激烈的模板巫术。结果,最后的类(我需要创建的实例)可能有几个继承的空结构。由于这个事实,他们中的一部分最终可能会被夸大。最糟糕的是,他们的内存布局实际上取决于继承的顺序。

如果有可能的话,我想摆脱这一切。

是否有一个C ++编译器可以配置为消除这种空间浪费,实际上是在破坏标准?

修改

我的意思是:

struct Empty1 {};
struct Empty2 {};

struct NonEmpty {
    int Value;
};

struct MyClass1
    :public NonEmpty
    ,public Empty1
    ,public Empty2
{
};

struct MyClass2
    :public Empty1
    ,public NonEmpty
    ,public Empty2
{
};

struct MyClass3
    :public Empty1
    ,public Empty2
    ,public NonEmpty
{
};

STATIC_ASSERT(sizeof(MyClass1) == 8);
STATIC_ASSERT(sizeof(MyClass2) == 4);
STATIC_ASSERT(sizeof(MyClass3) == 8);

不仅空结构会使对象膨胀(当多个这样的东西继承时),而且结果还取决于空结构的继承顺序。

5 个答案:

答案 0 :(得分:4)

空基优化是允许空基不会“膨胀”对象的内容,就像调用它一样。但是,您必须小心,以便对象不会从同一个空基继承两次,否则将不允许此优化。避免这种情况的一种方法是模拟空基,实例化它们,以便不会多次继承相同的空模板实例。

如果您的基类用于标记具体类,那么您可以考虑将您的设计更改为非侵入式类。

答案 1 :(得分:3)

在大多数现代c ++编译器中你会发现:

struct a { }; // empty struct
struct b : a { int x}; // inherits from empty struct.

assert(sizeof(b)==sizeof(int)); // despite sizeof(a) >0

这实际上是否能缓解您的顾虑?

答案 2 :(得分:2)

  

是否有可以配置的C ++编译器来消除这种空间浪费,......

是。 GCC-4.3.4

  

......以牺牲标准为代价?

不,该标准允许您的行为。

答案 3 :(得分:0)

如果您已经说过,基类可以是非零大小,否则它将与同一对象中相同类型的另一个实例具有相同的地址。

要“解决”这个问题,你需要确保你继承另一个类的空类或结构没有任何共同的祖先。

或者您可以自己手动布置类,但听起来您正在执行类似于从DirectX顶点声明枚举创建DirectX顶点类型的操作,因此这实际上没有帮助。

答案 4 :(得分:0)

g ++支持零大小数组,您可以使用以下之一:

struct Empty1 {
  int dummy[0];
};

struct Empty2 {
  int dummy[];
};

只有在使用'-pedantic'标志时才会生成警告。