Стандарты анонимных структур? И, действительно, что это * они?

MSDN считает, что анонимные структуры не являются стандартными в С++:

Расширение Microsoft C позволяет объявлять структурную переменную в пределах другой структуры, не указывая на это имя. Эти вложенные структуры называются анонимными структурами. С++ не позволяет анонимные структуры.

Вы можете получить доступ к членам анонимной структуры, как если бы они были членов в содержащей структуре.

@K-ballo соглашается.

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

С++ 11 говорит:

[C++11: 9/1]: [..] Спецификатор класса, чей класс-руководитель опускает имя класса-head, определяет неназванный класс.

и предоставляет целую грамматическую конструкцию для определения типа без имени.

С++ 03 не имеет этой явной формулировки, но аналогичным образом указывает, что identifier в определении типа является необязательным и ссылается на "неназванные классы" в 9.4.2/5 и 3.5/4.

  • Так MSDN ошибочно, и все это полностью стандартно?
  • Или есть какая-то тонкость, которую я пропускаю между "неназванными структурами/классами" и тем же, когда они используются в качестве элементов, которые мешают им быть охвачены этой функциональностью С++ 03/С++ 11?
  • Не хватает ли какой-либо фундаментальной разницы между "неназванной структурой" и "анонимной структурой"? Они похожи на синонимы.

Ответ 1

Весь стандартный текст относится к созданию "неназванной структуры":

struct {
   int hi;
   int bye;
};

Просто приятный дружественный тип, без доступного имени.

Стандартным образом он может быть создан как член:

struct Foo {
   struct {
      int hi;
      int bye;
   } bar;
};

int main()
{
   Foo f;
   f.bar.hi = 3;
}

Но "анонимная структура" является тонкой разницей -— это комбинация "неназванной структуры" и тот факт, что вы волшебным образом получаете членов из этого родительского объекта:

struct Foo {
   struct {
      int hi;
      int bye;
   }; // <--- no member name!
};

int main()
{
   Foo f;
   f.hi = 3;
}

Обратное к интуиции & dagger; это не просто создает неназванную структуру, вложенную witin Foo, но также автоматически дает вам "анонимный член", который делает члены доступными в пределах родительский объект.

Эта функциональность нестандартна. GCC поддерживает его, а также Visual С++. Заголовки API Windows используют эту функцию по умолчанию, но вы можете указать, что вы не хотите ее, добавив #define NONAMELESSUNION, прежде чем включать заголовочные файлы Windows.

Сравните со стандартной функциональностью "анонимных союзов", которые делают аналогичную вещь:

struct Foo {
   union {
      int hi;
      int bye;
   }; // <--- no member name!
};

int main()
{
   Foo f;
   f.hi = 3;
}

& dagger; Похоже, что хотя термин "неназванный" относится к типу (то есть "классу" или "структуре" ), термин "анонимный" относится вместо этого к фактическому (используя более старое значение "структуры", которое ближе к "объекту некоторого типа struct y" ). Вероятно, это был корень вашей первоначальной путаницы.

Ответ 2

То, что Microsoft называет анонимными структурами, не является стандартным. Неименованная структура - это просто обычная структура, которая не имеет имени. Вы не можете сделать это с одним, если вы также не определяете объект такого типа:

struct {
    int i;
    double d;
} my_object;

my_object.d = 2.3;

Анонимные союзы являются частью стандарта, и у них есть поведение, которое вы ожидаете от чтения Описание Microsoft их анонимных структур:

union {
    int i;
    double d;
};

d = 2.3;

Ответ 3

Стандартные разговоры об анонимных союзах: [9.5]/5

Объединение вида

union { member-specification } ;

называется анонимным объединением; он определяет неназванный объект неназванного типа. Спецификация участника анонимного объединения должна определять только нестатические элементы данных. [Примечание. Вложенные типы и функции не могут быть объявлены в анонимном объединении. -end note] Имена членов анонимного союза должны отличаться от имен любого другого объекта в области, в которой объявлен анонимный союз. Для целей поиска имени после определения анонимного объединения члены анонимного объединения считаются определенными в области, в которой объявлен анонимный союз. [Пример:

void f() {
    union { int a; const char* p; };
    a = 1;
    p = "Jennifer";
}

Здесь a и p используются как обычные (неявные) переменные, но поскольку они являются членами объединения, они имеют одинаковый адрес. -end пример]

Анонимные структуры, о которых говорит Microsoft, относятся к этой функции для unions, но применяются к structs. Это не просто неназванное определение, важно отметить, что элементы анонимного union/struct считаются определенными в области, в которой объявлен анонимный union/struct.

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