Являются ли "анонимные структуры" стандартными? И действительно, что они?

MSDN считает, что анонимные структуры нестандартны в C++:

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

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

@ К-балл согласен.

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

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

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

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

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

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

3 ответа

Решение

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

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

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

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

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

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

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

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

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

struct {
    int i;
    double d;
} my_object;

my_object.d = 2.3;

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

union {
    int i;
    double d;
};

d = 2.3;

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

Союз формы

union { member-specification } ;

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

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

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

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

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

Другие вопросы по тегам