Структура в C++ - это пользовательский тип данных, позволяющий группировать в себе набор переменных различных типов.

Объявление структур

Объявляется структура с помощью ключевого слова struct.

struct Person
{
    int id;
    std::string name;
    short age;
};

Person person;

Обращение к членам структуры

Доступ к членам структуры осуществляется через точку.

struct Person
{
    int id;
    std::string name;
    short age;
};

Person person;
person.id = 1;
person.name = "Person name";

std::cout << person.id << "\t" << person.name.c_str() << endl;

Инициализация структур

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

struct Person
{
    int id;
    std::string name;
};

// Инициализация каждого члена структуры по-отдельности
Person person1;
person1.id = 1;
person1.name = "Person #1 name";

// Инициализация списком значений
Person person2 = { 2, "Person #2 name" };

// Универсальная инициализация
Person person3 { 3, "Person #3 name" };

Начиная со стандарта C++11 при объявлении структуры для ее членов можно указать значения по-умолчанию.

struct Person
{
    int id;
    std::string name = "Default name";
} person;

std::cout << person.name.c_str() << std::endl;  // Default name

А начиная со стандарта C++14 структуры с объявленными по-умолчанию членами можно еще и инициализировать списком значений или универсальной инициализацией.

struct Person
{
    int id;
    std::string name = "Default name";
};

Person person1{ 1 };
Person person2{ 2, "Some name" };

std::cout << person1.name.c_str() << std::endl;    // Default name
std::cout << person2.name.c_str() << std::endl;    // Some name

Вложенные структуры

Структура может содержать в себе другие структуры. Их также можно инициализировать.

struct Address
{
    std::string state;
    std::string city = "Some City";
};

struct Person
{
    int id;
    std::string name = "Default name";
    Address address;
};

Person person = { 1, "Some name", { "Some State" } };

cout << person.address.city.c_str() << endl;  // Some City

Передача структур в функцию

Структуры можно передавать в функции и возвращать из функций. В этом случае происходит их передача через копирование.

struct Person
{
    int id;
    std::string name = "Default name";
};

Person change(Person person)
{
    person.name = "Changed name";
    return person;
}

Person person1 = { 1, "Some name" };
Person person2 = change(person1);

cout << person1.name.c_str() << endl;  // Some name
cout << person2.name.c_str() << endl;  // Changed name

Размер структуры

Размер структуры не может быть меньше размеров всех ее членов, но может быть больше, так как компилятор может добавлять промежутки между членами структуры для выравнивания по адресам памяти. Размер структуры можно получить с помощью оператора sizeof.

struct Person
{
    int id;
    short age;
};

Person person;

std::cout << sizeof(person.id) + sizeof(person.age) << std::endl;   // 6
std::cout << sizeof(person) << std::endl;                           // 8

Структуры и классы

Структуры в языке C++ практически ничем не отличаются от классов. Единственное отличие состоит в том, что члены структуры по-умолчанию объявляются как публичные, а в классе - как приватные.

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

struct Person
{
    int key;    // public
protected:
    int id;
public:
    std::string name = "Some Name";
};

struct NewPerson : Person
{
    void init()
    {
        key = 10;
        name = "New Name";
    }
};

NewPerson person;
person.init();

std::cout << person.key << std::endl;              // 10
std::cout << person.name.c_str() << std::endl;     // New Name

Объединения

Объединение - это объект, позволяющий нескольким переменным различных типов занимать один участок памяти. Объявление объединения похоже на объявление структуры, но используется ключевое слово union.

union Number
{
    int int_number;
    short short_number;
};

Number number;
number.int_number = 100;
std::cout << number.short_number << endl;    // 100
number.int_number = 100000;
std::cout << number.short_number << endl;   // -31072

Инициализация объединения

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

union Number
{
    int int_number;
    short short_number;
};

Number number = { 65535 };
std::cout << number.short_number << endl;    // -1

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

union Number
{
    int int_number = 65535;
    short short_number;
} number;

std::cout << number.short_number << endl;    // -1

Также для инициализации объединения можно использовать конструктор.

union Number
{
    int int_number;
    short short_number;
    Number() { int_number = 65535; }
} number;

std::cout << number.short_number << endl;    // -1