Стандарты анонимных структур? И, действительно, что это * они?
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.
Насколько я знаю, такого поведения для неназванных структур в стандарте не существует. Обратите внимание, что в приведенном примере вы можете достичь того, что не могло бы быть иначе, например совместного использования памяти для переменных в стеке, в то время как анонимные структуры ничего нового не добавили в таблицу.