Структуры в C++: чем отличается struct от typedef struct — разбор для новичков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Почему новички путаются в struct и typedef struct?

Если вы когда-нибудь заглядывали на Stack Overflow в поисках ответа на вопрос «Difference between 'struct' and 'typedef struct' in C++?», то наверняка заметили, что эта тема собрала тысячи просмотров. И это не случайно. Многие начинающие C++ разработчики, особенно те, кто пришёл из мира C или читает старые учебники, натыкаются на странный синтаксис с typedef struct и искренне недоумевают: зачем писать лишнее слово, если можно просто написать struct?

В этой статье мы раз и навсегда разберёмся, в чём разница между struct и typedef struct в современном C++. Мы посмотрим на исторические корни этой путаницы, напишем несколько примеров кода и дадим чёткие рекомендации, как писать правильно. Поехали!

Что такое struct в C++?

Начнём с базы. Структура (struct) в C++ — это пользовательский тип данных, который объединяет несколько переменных (полей) под одним именем. В отличие от класса, все члены структуры по умолчанию имеют модификатор доступа public, но в остальном struct и class в C++ практически идентичны (да, структура может иметь методы, конструкторы и даже наследование).

Объявление структуры в современном C++ выглядит так:

// Простая структура
struct Point {
    int x;
    int y;
};

int main() {
    Point p1;          // ОК: создаём объект
    p1.x = 10;
    p1.y = 20;
    return 0;
}

Всё просто и элегантно. Но откуда тогда берётся typedef struct?

Историческая справка: наследие языка C

Дело в том, что в языке C, чтобы создать переменную своего структурного типа, нужно было обязательно писать ключевое слово struct перед именем структуры. Например:

// В C так:
struct Point p1;  // без слова struct — ошибка

Чтобы избавиться от этого неудобства, программисты на C придумали трюк с typedef:

// C-стиль: typedef + struct
typedef struct {
    int x;
    int y;
} Point;

int main() {
    Point p1;  // теперь можно без struct
    return 0;
}

Этот синтаксис создаёт псевдоним (alias) для безымянной структуры. В C это было очень удобно. Но в C++ всё работает иначе.

А нужен ли typedef struct в C++?

Короткий ответ: нет, не нужен. В современном C++ (начиная со стандарта C++98 и далее) имя структуры автоматически становится именем типа. Вы можете использовать его без ключевого слова struct.

Сравните два подхода:

// Подход 1: чистый C++ (рекомендуется)
struct Point {
    int x, y;
};

Point p1;  // OK

// Подход 2: устаревший C-стиль (не рекомендуется)
typedef struct {
    int x, y;
} Point;

Point p2;  // тоже OK, но зачем лишнее?

Оба варианта скомпилируются, но первый — короче, понятнее и соответствует современным стандартам кодирования. Второй вариант — это просто привычка, перешедшая из C.

Когда typedef struct всё ещё может пригодиться?

Есть несколько ситуаций, когда typedef struct в C++ может быть оправдан:

  • Кросс-платформенный код на C и C++. Если вы пишете заголовочный файл, который должен компилироваться и в C, и в C++ (например, для библиотеки), то лучше использовать typedef struct — так код будет работать везде.
  • Создание псевдонима для сложного типа. Иногда typedef используют с шаблонами или указателями на структуры, чтобы упростить синтаксис.
  • Совместимость с легаси-кодом. Если вы поддерживаете старый проект, написанный в C-стиле, лучше не ломать существующий стиль.

Но если вы пишете новый проект на чистом C++, забудьте про typedef struct — используйте просто struct.

Разница между struct и typedef struct: пошаговый разбор

Давайте разложим всё по полочкам. Основные отличия между этими двумя подходами в контексте C++:

1. Синтаксис и читаемость

Без typedef:

struct MyStruct { int a; };
MyStruct obj;

С typedef:

typedef struct { int a; } MyStruct;
MyStruct obj;

Второй вариант длиннее на одно слово, а при большом количестве структур код становится замусоренным. Кроме того, безымянная структура (без имени после struct) не может ссылаться сама на себя — например, для создания связанного списка вам понадобится имя.

2. Возможность самоссылки

Если вы объявляете структуру, которая содержит указатель на саму себя (например, для узла списка), то typedef struct без имени структуры не сработает:

// Так нельзя:
typedef struct {
    int data;
    Node* next;  // Ошибка: Node ещё не определён
} Node;

// А так — можно (с именем структуры):
typedef struct Node {
    int data;
    struct Node* next;  // в C приходилось писать struct Node*
} Node;

// В C++ гораздо проще:
struct Node {
    int data;
    Node* next;  // имя структуры уже доступно внутри неё
};

Как видите, в C++ самоссылка решается естественно и без лишних танцев с typedef.

3. Совместимость с шаблонами и STL

В C++ структуры отлично работают с шаблонами, контейнерами STL и алгоритмами. typedef struct не даёт никаких преимуществ, а иногда даже мешает:

#include <vector>

struct Point { int x, y; };

std::vector<Point> points;  // работает

То же самое с typedef struct будет работать, но зачем усложнять?

Практический пример: что выбрать новичку?

Представьте, что вы пишете программу для хранения информации о студентах. Вот как это выглядит в двух стилях:

// Стиль C (typedef struct) — устаревший
typedef struct {
    char name[50];
    int age;
    double grade;
} Student;

// Стиль C++ (просто struct) — современный
struct Student {
    std::string name;
    int age;
    double grade;
};

int main() {
    Student s1 = {"Alice", 20, 4.5};
    Student s2;
    s2.name = "Bob";
    s2.age = 22;
    s2.grade = 3.8;
    return 0;
}

Второй вариант использует std::string вместо сырого масси

Блоги

Рекомендаций по книгам