Разница между 'struct' и 'typedef struct' в C++?
В C++ есть ли разница между следующими определениями:
struct Foo { ... };
и:
typedef struct { ... } Foo;
Дело в том, что оба варианта, похоже, создают тип с именем Foo
, но могут ли они иметь какие-либо различия в функциональности или использовании? Является ли использование typedef
обязательным в C++ для работы со структурами, или достаточно просто определить структуру с именем? Буду признателен за объяснение!
4 ответ(ов)
Одно важное отличие заключается в том, что typedef
нельзя предварительно объявить. Поэтому для использования typedef
вам необходимо #include
файл, содержащий этот typedef
, что означает, что все файлы, которые делают #include
ваш .h
, также включают этот файл, даже если он им не нужен, и так далее. Это может значительно повлиять на время сборки в крупных проектах.
Без использования typedef
в некоторых случаях вы можете просто добавить предварительное объявление struct Foo;
в верхней части вашего .h
файла и включить определение структуры только в вашем .cpp
файле.
Да, разница действительно существует, но она тонкая. Посмотрите на это так: struct Foo
вводит новый тип. Во втором случае создаётся псевдоним с именем Foo (а не новый тип) для анонимного типа struct
.
Вот что говорится в стандарте:
7.1.3 Спецификатор typedef
1 [...]
Имя, объявленное с помощью спецификатора typedef, становится именем типа. В пределах области его объявления имя типа синтаксически эквивалентно ключевому слову и обозначает тип, связанный с идентификатором, как описано в разделе 8. Таким образом, имя типа является синонимом другого типа. Имя типа не вводит новый тип, как это делает объявление класса (9.1) или перечисления.
Если декларация typedef определяет анонимный класс (или перечисление), то первое имя типа, объявленное в этой декларации, будет использоваться для обозначения класса (или перечисления) исключительно для целей линковки (3.5). Например:
typedef struct { } *ps, S; // S - это имя класса для целей линковки
Таким образом, typedef всегда используется как заместитель/синоним для другого типа.
Вы не можете использовать предварительное объявление с typedef struct
. Структура в этом случае является анонимным типом, и у вас нет фактического имени для предварительного объявления.
Вот пример:
typedef struct {
int one;
int two;
} myStruct;
Попытка сделать предварительное объявление таким образом не сработает:
struct myStruct; // предварительное объявление не сработает
void blah(myStruct* pStruct);
// ошибка C2371: 'myStruct' : переопределение; разные базовые типы
Это происходит потому, что myStruct
— это псевдоним для анонимного типа, и компилятор не знает, как обрабатывать такое предварительное объявление. Чтобы исправить это, вам нужно использовать имя для структуры в объявлении. Например:
struct MyStruct {
int one;
int two;
};
typedef struct MyStruct myStruct;
void blah(myStruct* pStruct);
Теперь компилятор сможет распознать как struct MyStruct
, так и myStruct
, и ошибок не возникнет.
Важное отличие между typedef struct
и struct
в C++ заключается в том, что инициализация членов в typedef struct
не будет работать.
// 'x' в этом структуре НЕ будет инициализировано в ноль
typedef struct { int x = 0; } Foo;
// 'x' в этой структуре БУДЕТ инициализировано в ноль
struct Foo { int x = 0; };
Причина в том, что в C++ C++11 и позже, стандарт поддерживает инициализацию членов класса непосредственно внутри объявления структуры, но для typedef struct
эта возможность не реализована. Это связано с тем, что typedef struct
фактически создает алиас для структуры, определенной на уровне C, где такие инициализации отсутствуют.
Какова разница между 'typedef' и 'using'?
В чем разница между #include <filename> и #include "filename"?
Когда использовать виртуальные деструкторы?
Циклы в программном обеспечении для семейных деревьев
Что означает 'const' в конце объявления метода класса?