根据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);
不仅空结构会使对象膨胀(当多个这样的东西继承时),而且结果还取决于空结构的继承顺序。
答案 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'标志时才会生成警告。