大小结构

Zero-sized struct

本文关键字:结构      更新时间:2023-10-16

根据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);

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

空基优化将允许空基不"膨胀"对象。但是,您必须小心,以免对象两次继承相同的空基,否则将不允许进行此优化。避免这种情况的一种方法是将空基模板化,对它们进行实例化,使同一个空模板实例化不会被继承超过一次。

如果你的基类是用来标记具体类的,那么你可以考虑把你的设计改成非侵入式的

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

struct a { }; // empty struct
struct b : a { int x}; // inherits from empty struct.
assert(sizeof(b)==sizeof(int)); // despite sizeof(a) >0

这实际上减轻了你的担忧吗?

有没有c++编译器可以配置来消除这种空间浪费,…

是的。gcc-4.3.4

…实际上是以违反标准为代价的吗?

不,标准允许你想要的行为

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

struct Empty1 {
  int dummy[0];
};

struct Empty2 {
  int dummy[];
};

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

如果基类与同一对象中相同类型的另一个实例具有相同的地址,则基类的大小可以为非零。

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

或者你可以自己手动布局类,但这听起来像是你在做一些事情,比如从DirectX顶点声明枚举中创建DirectX顶点类型,所以这并没有真正的帮助。