ПрограммированиеC++ разработчик

Опишите правила пяти и трёх (Rule of Three / Rule of Five) в C++11 и их важность при проектировании классов.

Проходите собеседования с ИИ помощником Hintsage

Ответ.

Правило трёх: если класс управляет ресурсом (например, памятью), то при явной реализации одного из следующих методов нужно реализовать и остальные:

  • Деструктор
  • Копирующий конструктор
  • Копирующий оператор присваивания

C++11: Правило пяти – добавились перемещающие операции:

  • Перемещающий конструктор
  • Перемещающий оператор присваивания

Нарушение этого правила приводит к ошибкам владения ресурсами, таким как двойное удаление или утечка памяти.

Пример кода:

class Buffer { char* data; public: Buffer(size_t sz) : data(new char[sz]) {} ~Buffer() { delete[] data; } Buffer(const Buffer& other) : data(new char[strlen(other.data)+1]) { strcpy(data, other.data); } Buffer& operator=(const Buffer& other) { if (&other != this) { delete[] data; data = new char[strlen(other.data)+1]; strcpy(data, other.data); } return *this; } // move-семантика в C++11+: Buffer(Buffer&& other) noexcept : data(other.data) { other.data = nullptr; } Buffer& operator=(Buffer&& other) noexcept { if (&other != this) { delete[] data; data = other.data; other.data = nullptr; } return *this; } };

Вопрос с подвохом.

Достаточно ли реализовать только деструктор, если класс управляет указателем?

Нет. Без копирующих и перемещающих операций при копировании будет происходить двойное удаление памяти. Например:

Buffer a(10); Buffer b = a; // b и a будут удалять один и тот же указатель!

Примеры реальных ошибок из-за незнания тонкостей темы.


История

В платформе агрегирования данных для телекоммуникаций все классы прописывали только деструктор. После рефакторинга структуры случилось массовое падение на double free: копирование объектов производило случайные поведения.


История

В проекте мобильной игры забыли реализовать move-конструктор для контейнерного класса буфера. При перемещении объект копировался, что давало лишнее копирование данных и просадки производительности.


История

В библиотеке сериализации структуры данных при возврате объекта из функции возвращался временный объект, а копирующий конструктор делал shallow copy указателя. Возникло множество утечек, проявившихся лишь спустя месяцы работы.