简体   繁体   English

零大小的结构

[英]Zero-sized struct

According to the C++ standard (inherited from C) empty structs have a non-zero size nevertheless. 根据C ++标准(继承自C),空结构仍然具有非零大小。 The reason for this (pitiful IMHO) is that two distinct variables should have different addresses. 这个(可怜的恕我直言)的原因是两个不同的变量应该有不同的地址。 Now, inheriting an empty struct does not always "inflate" the object. 现在,继承一个空结构并不总是“膨胀”该对象。 But in some situations this is the case. 但在某些情况下情况就是这样。

I have a pretty sophisticated classes architecture, involving fierce template voodoo. 我有一个相当复杂的类架构,涉及激烈的模板巫术。 As the result the final classes (instances of which I need to create) may have several empty structs inherited. 结果,最后的类(我需要创建的实例)可能有几个继承的空结构。 Due to this fact part of them may be inflated eventually. 由于这个事实,他们中的一部分最终可能会被夸大。 And the worst part is that their memory layout actually depends on the order of inheritance. 最糟糕的是,他们的内存布局实际上取决于继承的顺序。

I'd like to get rid of all this, if it's possible. 如果有可能的话,我想摆脱这一切。

Is there a C++ compiler that can be configured to eliminate this space waste, in expense of breaking the standard actually? 是否有一个C ++编译器可以配置为消除这种空间浪费,实际上是打破标准的代价?

Edit: 编辑:

I mean this: 我是说这个:

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

Not only empty structs inflate the object (when more than one such a thing inherited), but also the result depends on the order of inheritance of the empty structs. 不仅空结构会使对象膨胀(当多个这样的东西继承时),而且结果还取决于空结构的继承顺序。

The Empty Base Optimization is what will allow an empty base to not "inflate" the object, as you call it. 空基优化是允许空基不要“膨胀”对象的东西,就像你调用它一样。 However, you must be careful so that an object does not inherit from the same empty base twice or this optimization won't be allowed. 但是,您必须小心,以便对象不会从同一个空基继承两次,否则将不允许此优化。 A way to avoid this is to template the empty bases, instantiating them so that no same empty template instantiation will be inherited more than once. 避免这种情况的一种方法是对空基础进行模板化,实例化它们,以便不会多次继承相同的空模板实例。

If your base classes are used to tag concrete classes, then you could consider changing your design to a non-intrusive one. 如果您的基类用于标记具体类,那么您可以考虑将您的设计更改为非侵入式设计。

You will find, in most modern c++ compilers that: 在大多数现代c ++编译器中,您会发现:

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

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

Does that, practically, assuage your concerns? 这实际上是否能缓解您的顾虑?

Is there a C++ compiler that can be configured to eliminate this space waste, ... 是否有可以配置的C ++编译器来消除这种空间浪费,......

Yes. 是。 gcc-4.3.4 GCC-4.3.4

... in expense of breaking the standard actually? ......实际上打破了标准的代价?

No, the standard allows your desired behavior. 不,该标准允许您期望的行为。

g++ supports zero size arrays, you can use one of: g ++支持零大小数组,您可以使用以下之一:

struct Empty1 {
  int dummy[0];
};

or 要么

struct Empty2 {
  int dummy[];
};

It generates warning, only if the '-pedantic' flags is used. 只有在使用'-pedantic'标志时,它才会生成警告。

A base class can be of non-zero size if, as you already stated, it would otherwise have the same address as another instance of the same type in the same object. 如果您已经说过,它将具有与同一对象中相同类型的另一个实例相同的地址,则基类可以是非零大小。

To "solve" this problem, you need to ensure that the empty classes or structs you inherit another class from do not have any ancestors in common. 要“解决”这个问题,你需要确保你继承另一个类的空类或结构没有任何共同的祖先。

Or you can manually lay out the class yourself, but it sounds like you are doing something like creating a DirectX vertex type from the DirectX vertex declaration enumeration, so that wouldn't really help. 或者您可以自己手动布置类,但听起来您正在执行类似于从DirectX顶点声明枚举创建DirectX顶点类型的操作,因此这实际上没有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM