Подтвердить что ты не робот

Структура нулевого размера

В соответствии со стандартом С++ (унаследованным от C) пустые структуры имеют, тем не менее, ненулевой размер. Причиной этого (жалким ИМХО) является то, что две разные переменные должны иметь разные адреса. Теперь наследование пустой структуры не всегда "раздувает" объект. Но в некоторых ситуациях это так.

У меня довольно сложная архитектура классов, включающая жестокий шаблон voodoo. В результате конечные классы (экземпляры которых мне нужно создать) могут иметь несколько пустых структур, унаследованных. Из-за этого часть их может быть раздута в конце концов. И хуже всего то, что их макет памяти фактически зависит от порядка наследования.

Я бы хотел избавиться от всего этого, если это возможно.

Есть ли компилятор С++, который может быть сконфигурирован для устранения этих космических отходов, за счет стандартного нарушения стандарта?

Edit:

Я имею в виду это:

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

Не только пустые структуры раздувают объект (когда более чем одна такая вещь унаследована), но и результат зависит от порядка наследования пустых структур.

4b9b3361

Ответ 1

Есть ли компилятор С++, который можно настроить для устранения этого космического мусора,...

Да. gcc-4.3.4: http://ideone.com/YJplC

... за счет нарушения стандарта на самом деле?

Нет, стандарт позволяет ваше поведение.

Ответ 2

Оптимизация пустой базы - это то, что позволит пустой базе не "раздувать" объект, как вы его называете. Однако вы должны быть осторожны, чтобы объект не наследовал от одной и той же пустой базы дважды, или эта оптимизация не будет разрешена. Способ избежать этого заключается в шаблоне пустых баз, создавая их, чтобы один и тот же пустой экземпляр шаблона не был унаследован более чем один раз.

Если ваши базовые классы используются для обозначения конкретных классов, вы можете рассмотреть возможность изменения дизайна на неинтрузивный.

Ответ 3

В большинстве современных компиляторов С++ вы найдете:

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

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

Это, практически, успокаивает ваши проблемы?

Ответ 4

Базовый класс может иметь ненулевой размер, если, как вы уже сказали, в противном случае он имел бы тот же адрес, что и другой экземпляр одного и того же типа в одном и том же объекте.

Чтобы "решить" эту проблему, вам нужно убедиться, что пустые классы или структуры, наследуемые другим классом, не имеют общих предков.

Или вы можете вручную выложить класс самостоятельно, но похоже, что вы делаете что-то вроде создания вершинного типа DirectX из перечисления декларации вершин DirectX, поэтому это не помогло бы.

Ответ 5

g++ поддерживает массивы нулевого размера, вы можете использовать один из:

struct Empty1 {
  int dummy[0];
};

или

struct Empty2 {
  int dummy[];
};

Он генерирует предупреждение, только если используются флаги '-pedantic'.