Перейти к основному содержимому

200 вопросов по C++

200 вопросов по C++

Основы языка C++

Вопрос

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

Ответ

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


Вопрос

Каковы основные особенности C++?

Ответ

Основные особенности C++ включают:

  • Поддержку объектно-ориентированного программирования (инкапсуляция, наследование, полиморфизм);
  • Обобщённое программирование через шаблоны;
  • Ручное управление памятью с помощью указателей и операторов new/delete;
  • RAII (Resource Acquisition Is Initialization) как идиома управления ресурсами;
  • Высокую производительность и близость к аппаратному уровню;
  • Совместимость с большей частью кода на C.

Вопрос

Что такое компилятор и как он работает с C++?

Ответ

Компилятор — это программа, преобразующая исходный код на C++ в машинный код или объектный файл. Процесс компиляции включает предварительную обработку (макроподстановки, включение заголовков), синтаксический и семантический анализ, оптимизацию и генерацию кода. Для сборки исполняемого файла объектные файлы далее передаются линковщику.


Вопрос

Что такое стандартная библиотека C++ (Standard Library)?

Ответ

Стандартная библиотека C++ предоставляет набор готовых компонентов: контейнеры (vector, map, set), алгоритмы (sort, find), итераторы, потоки ввода-вывода (iostream), утилиты (pair, optional), функциональные объекты и многое другое. Она тесно интегрирована с языком и активно использует шаблоны.


Вопрос

Какие версии стандарта C++ существуют?

Ответ

Основные версии стандарта C++:

  • C++98 — первая стандартизация;
  • C++03 — незначительные исправления;
  • C++11 — крупное обновление (автоматический вывод типов, лямбда-выражения, умные указатели);
  • C++14 — уточнения и дополнения к C++11;
  • C++17 — структурированное связывание, std::optional, параллельные алгоритмы;
  • C++20 — концепции, модули, корутины, диапазоны;
  • C++23 — дальнейшие улучшения, например, std::expected.

Вопрос

Что такое main() функция?

Ответ

Функция main() — это точка входа в программу на C++. Исполняемая программа начинает выполнение с этой функции. Её сигнатура может быть int main() или int main(int argc, char* argv[]). Возвращаемое значение типа int передаётся операционной системе как код завершения.


Вопрос

Что означает ключевое слово const?

Ответ

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


Вопрос

Что такое комментарии в C++ и какие виды существуют?

Ответ

Комментарии — это участки кода, игнорируемые компилятором. В C++ есть два вида:

  • Однострочные: // комментарий;
  • Многострочные: /* комментарий */.

Вопрос

Что такое идентификатор?

Ответ

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


Вопрос

Что такое область видимости (scope)?

Ответ

Область видимости определяет, где в программе можно использовать имя (переменную, функцию и т.д.). В C++ существуют глобальная, локальная (внутри блока {}), классовая и пространства имён. Переменная доступна только внутри своей области видимости и вложенных областей.


Типы данных и переменные

Вопрос

Какие встроенные типы данных есть в C++?

Ответ

Встроенные типы данных включают:

  • Целочисленные: char, short, int, long, long long;
  • Вещественные: float, double, long double;
  • Логический: bool;
  • Символьный: char, wchar_t, char8_t, char16_t, char32_t;
  • Пустой тип: void.

Вопрос

Что такое auto?

Ответ

Ключевое слово auto позволяет компилятору автоматически вывести тип переменной на основе её инициализатора. Например:

auto x = 42;        // x имеет тип int
auto y = 3.14; // y имеет тип double

Вопрос

Что такое nullptr?

Ответ

nullptr — это ключевое слово, представляющее нулевой указатель. Оно заменяет макрос NULL и литерал 0, устраняя неоднозначности при перегрузке функций и повышая типобезопасность.


Вопрос

В чём разница между int и long?

Ответ

Размер int обычно составляет 4 байта (32 бита) на большинстве современных систем, а long — не менее 4 байт, но может быть 8 байт на 64-битных платформах. Точный размер зависит от реализации и архитектуры. Стандарт гарантирует только минимальные размеры: int ≥ 16 бит, long ≥ 32 бита.


Вопрос

Что такое typedef и using?

Ответ

typedef и using создают псевдонимы для типов. Пример:

typedef unsigned int uint;
using uint = unsigned int;

Современный стиль предпочитает using, особенно для шаблонов.


Вопрос

Что такое литералы в C++?

Ответ

Литералы — это фиксированные значения, записываемые непосредственно в коде:

  • Целочисленные: 42, 0xFF;
  • Вещественные: 3.14, 1e5;
  • Строковые: "hello";
  • Символьные: 'A';
  • Булевы: true, false;
  • Указательные: nullptr.

Вопрос

Что такое инициализация переменной?

Ответ

Инициализация — это присвоение начального значения переменной при её объявлении. В C++ поддерживаются несколько форм:

  • Копирующая: int x = 5;
  • Прямая: int x(5);
  • Унифицированная (uniform): int x{5}; — предпочтительна, так как запрещает сужающие преобразования.

Вопрос

Что такое enum и enum class?

Ответ

enum определяет перечислимый тип с именованными константами. Обычный enum не изолирован по области видимости и неявно преобразуется в целое число.
enum class (scoped enum) изолирован в своей области видимости и не допускает неявных преобразований:

enum class Color { Red, Green, Blue };
Color c = Color::Red;

Вопрос

Что такое volatile?

Ответ

Ключевое слово volatile указывает компилятору, что значение переменной может изменяться вне контроля программы (например, аппаратным прерыванием). Это запрещает оптимизации, связанные с кэшированием значения в регистрах.


Вопрос

Можно ли объявить переменную без типа?

Ответ

Нет. C++ — статически типизированный язык, и каждая переменная должна иметь тип, явно указанный или выведенный (например, через auto).


Операторы и выражения

Вопрос

Какие арифметические операторы есть в C++?

Ответ

Арифметические операторы: +, -, *, /, % (остаток от деления). Все работают с числовыми типами. Оператор % применим только к целым типам.


Вопрос

Что такое приоритет операторов?

Ответ

Приоритет операторов определяет порядок вычисления выражений. Например, * и / имеют более высокий приоритет, чем + и -. Скобки () могут изменить порядок вычислений.


Вопрос

Что делают операторы инкремента и декремента?

Ответ

Операторы ++ и -- увеличивают или уменьшают значение переменной на 1. Существуют префиксная (++x) и постфиксная (x++) формы. Префиксная возвращает новое значение, постфиксная — старое.


Вопрос

Что такое тернарный оператор?

Ответ

Тернарный оператор имеет форму условие ? выражение1 : выражение2. Если условие истинно, вычисляется выражение1, иначе — выражение2. Пример:

int max = (a > b) ? a : b;

Вопрос

Что такое оператор присваивания?

Ответ

Оператор = присваивает значение правого операнда левому. Он возвращает ссылку на левый операнд, что позволяет цепочку присваиваний: a = b = c = 0;.


Вопрос

Что такое составные операторы присваивания?

Ответ

Составные операторы объединяют арифметическую или побитовую операцию с присваиванием: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=.


Вопрос

Что такое побитовые операторы?

Ответ

Побитовые операторы работают с двоичным представлением целых чисел:

  • & — побитовое И;
  • | — побитовое ИЛИ;
  • ^ — побитовое исключающее ИЛИ;
  • ~ — побитовое НЕ;
  • << — сдвиг влево;
  • >> — сдвиг вправо.

Вопрос

Что такое логические операторы?

Ответ

Логические операторы:

  • && — логическое И (с коротким замыканием);
  • || — логическое ИЛИ (с коротким замыканием);
  • ! — логическое НЕ.
    Они работают с булевыми значениями или приводимыми к bool типами.

Вопрос

Что такое оператор sizeof?

Ответ

Оператор sizeof возвращает размер (в байтах) типа или выражения во время компиляции. Например:

sizeof(int)    // обычно 4
sizeof(arr) // размер всего массива в байтах

Вопрос

Что такое оператор ?:?

Ответ

Оператор ?: — это тернарный условный оператор. Он выбирает одно из двух значений в зависимости от условия. Пример:

std::string status = (score >= 60) ? "Pass" : "Fail";

Указатели и ссылки

Вопрос

Что такое указатель в C++?

Ответ

Указатель — это переменная, хранящая адрес другой переменной в памяти. Указатель имеет тип, соответствующий типу данных, на которые он указывает. Например:

int x = 42;
int* ptr = &x; // ptr хранит адрес переменной x

Вопрос

Как получить значение по указателю?

Ответ

Для получения значения, на которое указывает указатель, используется оператор разыменования *. Пример:

int x = 10;
int* p = &x;
int value = *p; // value == 10

Вопрос

Что такое нулевой указатель?

Ответ

Нулевой указатель — это указатель, не ссылающийся ни на какой объект или функцию. В современном C++ для этого используется ключевое слово nullptr.


Вопрос

Можно ли изменять значение, на которое указывает указатель?

Ответ

Да, если указатель не объявлен как указатель на константу (const T*) и сам объект не является константным. Пример:

int x = 5;
int* p = &x;
*p = 10; // x теперь равно 10

Вопрос

Что такое указатель на константу и константный указатель?

Ответ

  • const int* p — указатель на константное целое: значение нельзя изменить через p, но сам p можно переназначить.
  • int* const p = &x — константный указатель на целое: адрес фиксирован, но значение можно менять.
  • const int* const p = &x — константный указатель на константное значение: ничего нельзя изменить.

Вопрос

Что такое арифметика указателей?

Ответ

Арифметика указателей позволяет выполнять сложение и вычитание целых чисел с указателями. При добавлении n к указателю он перемещается на n * sizeof(тип) байт. Это особенно полезно при работе с массивами:

int arr[3] = {10, 20, 30};
int* p = arr; // указывает на arr[0]
int* q = p + 1; // указывает на arr[1]

Вопрос

Что такое ссылка в C++?

Ответ

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

int x = 5;
int& ref = x; // ref — это другое имя для x
ref = 10; // x теперь равно 10

Вопрос

В чём разница между указателем и ссылкой?

Ответ

  • Ссылка должна быть инициализирована при объявлении и не может быть изменена.
  • Указатель может быть переназначен и может быть нулевым.
  • Ссылка не занимает дополнительного места в памяти (это псевдоним), тогда как указатель — полноценная переменная, хранящая адрес.
  • Синтаксис работы со ссылкой проще: нет необходимости в * или &.

Вопрос

Можно ли создать ссылку на временное значение?

Ответ

Можно создать константную ссылку на временное значение. Это продлевает время жизни временного объекта до конца области видимости ссылки:

const std::string& s = getTempString();  // безопасно

Неконстантная ссылка на временный объект запрещена.


Вопрос

Что такое «висячий» указатель или ссылка?

Ответ

«Висячий» указатель или ссылка — это указатель или ссылка, ссылающиеся на объект, который уже уничтожен (например, локальная переменная после выхода из функции). Использование таких указателей приводит к неопределённому поведению.


Функции

Вопрос

Как объявляется функция в C++?

Ответ

Функция объявляется с указанием возвращаемого типа, имени и списка параметров:

int add(int a, int b) {
return a + b;
}

Вопрос

Что такое сигнатура функции?

Ответ

Сигнатура функции включает её имя и типы параметров (в порядке их следования). Возвращаемый тип не входит в сигнатуру. Сигнатура определяет уникальность функции при перегрузке.


Вопрос

Что такое перегрузка функций?

Ответ

Перегрузка функций — это возможность объявить несколько функций с одним именем, но разными сигнатурами. Компилятор выбирает подходящую версию на основе типов переданных аргументов:

void print(int x);
void print(double x);
void print(const std::string& s);

Вопрос

Что такое параметры по умолчанию?

Ответ

Параметры по умолчанию — это значения, автоматически подставляемые компилятором, если аргумент не передан при вызове функции. Они указываются в объявлении функции справа налево:

void greet(std::string name, std::string greeting = "Hello") {
std::cout << greeting << ", " << name << "!\n";
}
greet("Alice"); // Hello, Alice!

Вопрос

Что такое передача по значению?

Ответ

При передаче по значению в функцию копируется фактическое значение аргумента. Изменения внутри функции не влияют на исходную переменную:

void inc(int x) { x++; }  // x — копия

Вопрос

Что такое передача по ссылке?

Ответ

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

void inc(int& x) { x++; }  // x — ссылка на оригинал

Вопрос

Когда следует использовать const в параметрах функции?

Ответ

Использование const в параметрах (особенно при передаче по ссылке или указателю) гарантирует, что функция не изменит переданный объект. Это повышает безопасность и читаемость:

void print(const std::vector<int>& v);  // v не будет изменён

Вопрос

Что такое встроенная функция (inline)?

Ответ

Ключевое слово inline является подсказкой компилятору заменить вызов функции её телом (инлайнинг), чтобы уменьшить накладные расходы на вызов. Современные компиляторы часто игнорируют эту подсказку и принимают решение самостоятельно.


Вопрос

Что такое рекурсивная функция?

Ответ

Рекурсивная функция — это функция, вызывающая саму себя. Она должна содержать условие завершения (базовый случай), иначе произойдёт бесконечная рекурсия и переполнение стека:

int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}

Вопрос

Что такое функция с переменным числом аргументов?

Ответ

Функция с переменным числом аргументов использует спецификатор ... в списке параметров. Такие функции реализуются с помощью макросов из <cstdarg> (va_list, va_start, va_arg, va_end). Пример — printf. В современном C++ предпочтительнее использовать шаблоны или std::initializer_list.


Вопрос

Что такое лямбда-выражение?

Ответ

Лямбда-выражение — это анонимная функция, определяемая прямо в месте использования. Она может захватывать переменные из окружающей области видимости:

auto square = [](int x) { return x * x; };
std::cout << square(5); // 25

Вопрос

Как работает захват переменных в лямбда-выражениях?

Ответ

Захват определяется в квадратных скобках []:

  • [x] — захват по значению;
  • [&x] — захват по ссылке;
  • [=] — захват всех видимых переменных по значению;
  • [&] — захват всех видимых переменных по ссылке;
  • [this] — захват указателя на текущий объект.

Вопрос

Что такое main — обычная функция?

Ответ

main — это обычная функция с особым статусом: она является точкой входа программы. Её нельзя вызывать рекурсивно, нельзя брать её адрес, и она не может быть переопределена.


Вопрос

Можно ли перегружать функцию main?

Ответ

Нет. Функция main не может быть перегружена. Допустимы только две сигнатуры: int main() и int main(int argc, char* argv[]).


Вопрос

Что такое функция-член класса?

Ответ

Функция-член класса — это функция, объявленная внутри определения класса. Она имеет доступ ко всем членам класса (включая закрытые) и неявно получает указатель this на текущий объект.


Вопрос

Что такое static функция-член?

Ответ

static функция-член принадлежит классу, а не конкретному объекту. Она не имеет доступа к нестатическим членам и не получает указатель this. Вызывается через имя класса: ClassName::func().


Вопрос

Что такое дружественная функция (friend)?

Ответ

Дружественная функция — это обычная функция (не член класса), имеющая доступ к закрытым и защищённым членам класса. Объявляется с ключевым словом friend внутри класса.


Вопрос

Что такое constexpr функция?

Ответ

constexpr функция — это функция, значение которой может быть вычислено во время компиляции, если все её аргументы являются константными выражениями. Тело такой функции должно удовлетворять строгим ограничениям (например, содержать только один return в C++11, но в более новых стандартах — почти любой код).


Вопрос

Что такое возврат по значению, по ссылке и по указателю?

Ответ

  • Возврат по значению создаёт копию результата.
  • Возврат по ссылке возвращает псевдоним существующего объекта (осторожно с локальными переменными!).
  • Возврат по указателю возвращает адрес объекта (также осторожно с локальными!).
    Пример безопасного возврата по ссылке:
const std::string& getName() const { return name_; }

Вопрос

Что такое функция с побочными эффектами?

Ответ

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


Классы и объекты

Вопрос

Что такое класс в C++?

Ответ

Класс — это пользовательский тип данных, объединяющий данные (поля) и функции (методы), работающие с этими данными. Класс определяет структуру и поведение объектов этого типа.


Вопрос

Что такое объект?

Ответ

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


Вопрос

Какие уровни доступа существуют в классе?

Ответ

В классе существуют три уровня доступа:

  • private — доступны только методам самого класса;
  • protected — доступны методам класса и его наследников;
  • public — доступны из любого места программы.

Вопрос

В чём разница между class и struct в C++?

Ответ

Основное различие — уровень доступа по умолчанию:

  • В class члены по умолчанию private;
  • В struct члены по умолчанию public.
    В остальном они полностью эквивалентны: оба поддерживают методы, конструкторы, наследование и т.д.

Вопрос

Что такое инкапсуляция?

Ответ

Инкапсуляция — это принцип объектно-ориентированного программирования, при котором данные и методы, работающие с ними, объединяются в один объект, а прямой доступ к внутреннему состоянию ограничивается через интерфейс (публичные методы).


Вопрос

Что такое метод класса?

Ответ

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


Вопрос

Что такое this?

Ответ

this — это константный указатель, доступный внутри нестатических методов класса. Он указывает на объект, для которого вызван метод. Используется для разрешения конфликтов имён или возврата ссылки на текущий объект.


Вопрос

Что такое константный метод?

Ответ

Константный метод — это метод, помеченный ключевым словом const после списка параметров. Такой метод гарантирует, что не будет изменять состояние объекта (не может модифицировать нестатические поля, кроме помеченных как mutable).


Вопрос

Что такое mutable?

Ответ

Ключевое слово mutable позволяет изменять поле класса даже внутри константных методов. Оно применяется к полям, которые логически не влияют на внешнее состояние объекта (например, кэш или счётчик вызовов).


Вопрос

Что такое агрегатный класс?

Ответ

Агрегатный класс — это класс (или структура), удовлетворяющий условиям:

  • Нет пользовательских конструкторов;
  • Нет закрытых или защищённых нестатических членов;
  • Нет виртуальных функций;
  • Нет базовых классов;
  • Нет фигурных скобок или равенств при инициализации нестатических членов.
    Такие классы можно инициализировать списком значений в фигурных скобках.

Конструкторы и деструкторы

Вопрос

Что такое конструктор?

Ответ

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


Вопрос

Какие виды конструкторов существуют?

Ответ

Основные виды конструкторов:

  • Конструктор по умолчанию — без параметров или со всеми параметрами по умолчанию;
  • Параметризованный конструктор — принимает аргументы;
  • Конструктор копирования — принимает константную ссылку на объект того же типа;
  • Конструктор перемещения — принимает rvalue-ссылку на объект того же типа (C++11 и новее).

Вопрос

Что такое конструктор по умолчанию?

Ответ

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


Вопрос

Что такое конструктор копирования?

Ответ

Конструктор копирования создаёт новый объект как копию существующего. Его сигнатура: ClassName(const ClassName&). Если не объявлен явно, компилятор сгенерирует его, выполнив побитовое копирование всех полей.


Вопрос

Когда вызывается конструктор копирования?

Ответ

Конструктор копирования вызывается при:

  • Инициализации объекта другим объектом того же типа;
  • Передаче объекта в функцию по значению;
  • Возврате объекта из функции по значению.

Вопрос

Что такое конструктор перемещения?

Ответ

Конструктор перемещения принимает rvalue-ссылку (ClassName&&) и передаёт ресурсы от временного объекта новому объекту, избегая дорогостоящего копирования. Это часть семантики перемещения, введённой в C++11.


Вопрос

Что такое список инициализации членов?

Ответ

Список инициализации членов — это синтаксис в конструкторе, позволяющий инициализировать поля до выполнения тела конструктора. Он записывается после двоеточия:

MyClass(int x) : value(x), name("default") {}

Это единственный способ инициализировать константные и ссылочные поля.


Вопрос

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

Ответ

Список инициализации выполняет прямую инициализацию, тогда как присваивание в теле сначала вызывает конструктор по умолчанию, а затем оператор присваивания. Для сложных типов это менее эффективно и может быть невозможно (например, для const или ссылок).


Вопрос

Что такое делегирующий конструктор?

Ответ

Делегирующий конструктор — это конструктор, который вызывает другой конструктор того же класса через список инициализации. Это позволяет избежать дублирования кода:

MyClass() : MyClass(0) {}  
MyClass(int x) : value(x) {}

Вопрос

Что такое деструктор?

Ответ

Деструктор — это специальный метод, вызываемый автоматически при уничтожении объекта. Он освобождает ресурсы, захваченные объектом (память, файловые дескрипторы и т.д.). Имя деструктора — ~ClassName.


Вопрос

Когда вызывается деструктор?

Ответ

Деструктор вызывается:

  • При выходе объекта из области видимости (для локальных переменных);
  • При удалении объекта через delete (для динамически выделенных объектов);
  • При завершении программы (для глобальных и статических объектов).

Вопрос

Можно ли перегружать деструктор?

Ответ

Нет. У класса может быть только один деструктор, и он не принимает параметров.


Вопрос

Что такое правило трёх (Rule of Three)?

Ответ

Правило трёх гласит: если класс требует явного определения одного из следующих — деструктора, конструктора копирования или оператора присваивания копированием — то, скорее всего, требуется определить все три. Это связано с корректным управлением ресурсами.


Вопрос

Что такое правило пяти (Rule of Five)?

Ответ

Правило пяти расширяет правило трёх для C++11 и новее: если требуется один из пяти специальных функций — деструктор, конструктор копирования, оператор присваивания копированием, конструктор перемещения, оператор присваивания перемещением — то, вероятно, нужны все пять.


Вопрос

Что делает компилятор, если не определить специальные функции?

Ответ

Если программист не определяет специальные функции, компилятор может сгенерировать их автоматически:

  • Конструктор по умолчанию — если нет других конструкторов;
  • Конструктор копирования и оператор присваивания — выполняют побитовое копирование;
  • Деструктор — пустой;
  • Конструктор и оператор перемещения — генерируются, если не определены копирующие и деструктор.

Вопрос

Что такое тривиальный конструктор или деструктор?

Ответ

Тривиальный конструктор (или деструктор) — это конструктор (деструктор), сгенерированный компилятором и не выполняющий никаких действий. Такие функции позволяют применять оптимизации, например, инициализацию через memcpy.


Вопрос

Что такое POD-тип (Plain Old Data)?

Ответ

POD-тип — это тип, совместимый с C: он должен быть тривиальным (тривиальные конструкторы, деструктор, операторы присваивания) и стандартным (стандартный layout — все поля одного уровня доступа, без виртуальных функций и базовых классов). Такие типы можно безопасно копировать побайтово.


Вопрос

Что такое = default и = delete?

Ответ

  • = default указывает компилятору сгенерировать специальную функцию (например, конструктор по умолчанию), даже если она была бы подавлена.
  • = delete запрещает использование функции (например, копирование):
MyClass(const MyClass&) = delete;

Вопрос

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

Ответ

Удаление конструктора копирования делает объект некопируемым. Это полезно для классов, управляющих уникальными ресурсами (например, дескрипторами файлов или потоками), где копирование не имеет смысла или опасно.


Операторы и перегрузка

Вопрос

Что такое перегрузка операторов?

Ответ

Перегрузка операторов — это возможность определить поведение встроенных операторов (например, +, ==, []) для пользовательских типов. Это позволяет использовать объекты классов в выражениях так же, как встроенные типы.


Вопрос

Какие операторы можно перегружать?

Ответ

Можно перегружать большинство операторов: арифметические (+, -, *, /), логические (&&, ||), побитовые (&, |, ^), операторы присваивания (=, +=), сравнения (==, !=, <), индексации ([]), вызова (()), разыменования (*, ->), потокового ввода-вывода (<<, >>) и другие.


Вопрос

Какие операторы нельзя перегружать?

Ответ

Нельзя перегружать следующие операторы:

  • :: (разрешение области видимости);
  • . (доступ к члену);
  • .* (доступ к члену через указатель на член);
  • ?: (тернарный условный оператор);
  • sizeof;
  • typeid.

Вопрос

Как перегрузить оператор как функцию-член?

Ответ

Оператор, перегруженный как функция-член, имеет неявный параметр this. Например, бинарный оператор + будет принимать один явный аргумент:

class Vec {
public:
Vec operator+(const Vec& other) const {
return Vec(x + other.x, y + other.y);
}
};

Вопрос

Как перегрузить оператор как свободную функцию?

Ответ

Свободная функция принимает все операнды как явные параметры. Это необходимо, когда левый операнд не является объектом класса (например, int + MyClass). Пример:

Vec operator+(const Vec& a, const Vec& b) {
return Vec(a.x + b.x, a.y + b.y);
}

Вопрос

Почему оператор присваивания часто перегружается как функция-член?

Ответ

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


Вопрос

Как правильно реализовать оператор присваивания?

Ответ

Корректная реализация включает проверку самоприсваивания и возврат ссылки на *this:

MyClass& operator=(const MyClass& other) {
if (this != &other) {
// освободить старые ресурсы
// скопировать новые
}
return *this;
}

Вопрос

Что такое оператор индексации []?

Ответ

Оператор [] позволяет объекту использоваться как контейнер с индексированным доступом. Обычно предоставляются две версии: одна для чтения (const), другая для записи:

T& operator[](size_t i);
const T& operator[](size_t i) const;

Вопрос

Что такое оператор вызова ()?

Ответ

Оператор () превращает объект в функциональный объект (функтор). Такой объект может вызываться как функция:

struct Adder {
int operator()(int a, int b) { return a + b; }
};
Adder add;
int result = add(3, 4); // 7

Вопрос

Как перегрузить операторы ввода и вывода (<<, >>)?

Ответ

Операторы << и >> перегружаются как свободные функции, принимающие ссылку на поток и объект:

std::ostream& operator<<(std::ostream& os, const MyClass& obj) {
os << obj.toString();
return os;
}

Наследование

Вопрос

Что такое наследование в C++?

Ответ

Наследование — это механизм, позволяющий одному классу (производному) получить свойства и методы другого класса (базового). Это способствует повторному использованию кода и реализации иерархий типов.


Вопрос

Как объявить производный класс?

Ответ

Производный класс объявляется с использованием синтаксиса:

class Derived : access Base {
// тело класса
};

где access — это public, protected или private.


Вопрос

Какие виды наследования существуют?

Ответ

Существуют три вида наследования:

  • public — публичные члены базового класса остаются публичными, защищённые — защищёнными;
  • protected — публичные и защищённые члены базового становятся защищёнными;
  • private — все члены базового класса становятся приватными в производном.

Вопрос

Что такое «является» (is-a) отношение?

Ответ

Отношение «является» означает, что объект производного класса можно рассматривать как объект базового класса. Это основа полиморфизма и корректного использования наследования.


Вопрос

Что происходит с конструкторами при наследовании?

Ответ

Конструктор производного класса обязан инициализировать базовый класс, явно или неявно. Если базовый класс не имеет конструктора по умолчанию, инициализация должна быть указана в списке инициализации:

Derived(int x) : Base(x) {}

Вопрос

Что такое порядок вызова конструкторов и деструкторов?

Ответ

При создании объекта сначала вызывается конструктор базового класса, затем — конструктор производного. При уничтожении порядок обратный: сначала деструктор производного, затем — базового.


Вопрос

Можно ли наследовать от нескольких классов?

Ответ

Да, C++ поддерживает множественное наследование: класс может наследовать от нескольких базовых классов одновременно.


Вопрос

Что такое ромбовидное наследование?

Ответ

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


Вопрос

Как решить проблему ромбовидного наследования?

Ответ

Проблема решается с помощью виртуального наследования. Базовый класс объявляется как виртуальный в промежуточных классах:

class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {}; // A — один подобъект

Вопрос

Что такое виртуальное наследование?

Ответ

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


Вопрос

Что такое абстрактный класс?

Ответ

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


Вопрос

Что такое чисто виртуальная функция?

Ответ

Чисто виртуальная функция — это виртуальная функция, помеченная как = 0. Она не имеет реализации в базовом классе и должна быть переопределена в производных классах:

virtual void draw() = 0;

Вопрос

Можно ли вызывать виртуальные функции из конструктора?

Ответ

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


Вопрос

Что такое сокрытие имён при наследовании?

Ответ

Если производный класс объявляет функцию с тем же именем, что и в базовом, но другой сигнатурой, то все перегрузки из базового класса становятся недоступны. Это называется сокрытием имён. Чтобы избежать этого, используется директива using:

using Base::func;

Вопрос

Что такое окончательный класс (final)?

Ответ

Ключевое слово final запрещает дальнейшее наследование от класса:

class Base final { /* ... */ };
// class Derived : Base {}; // ошибка компиляции

Полиморфизм и виртуальные функции

Вопрос

Что такое полиморфизм в C++?

Ответ

Полиморфизм — это возможность использовать объекты разных типов через единый интерфейс. В C++ он реализуется с помощью виртуальных функций и наследования: указатель или ссылка на базовый класс может вызывать переопределённые методы производных классов.


Вопрос

Что такое виртуальная функция?

Ответ

Виртуальная функция — это функция-член, объявленная с ключевым словом virtual в базовом классе. Она позволяет вызывать версию функции, определённую в производном классе, даже если вызов происходит через указатель или ссылку на базовый класс.


Вопрос

Как работает механизм виртуальных функций?

Ответ

Компилятор создаёт таблицу виртуальных функций (vtable) для каждого класса с виртуальными функциями. Каждый объект содержит скрытый указатель (vptr), ссылающийся на vtable своего типа. При вызове виртуальной функции используется vtable для определения реального адреса функции.


Вопрос

Что такое позднее связывание (динамическое связывание)?

Ответ

Позднее связывание — это определение вызываемой функции во время выполнения программы, а не компиляции. Оно используется при вызове виртуальных функций через указатель или ссылку на базовый класс.


Вопрос

Обязательно ли переопределять виртуальную функцию в производном классе?

Ответ

Нет. Производный класс может не переопределять виртуальную функцию. В этом случае будет использоваться реализация из ближайшего базового класса, где она определена.


Вопрос

Что делает ключевое слово override?

Ответ

Ключевое слово override указывает, что функция намеренно переопределяет виртуальную функцию из базового класса. Если сигнатура не совпадает, компилятор выдаст ошибку, что помогает избежать ошибок при перегрузке.


Вопрос

Что делает ключевое слово final применительно к функции?

Ответ

Ключевое слово final, применённое к виртуальной функции, запрещает её дальнейшее переопределение в производных классах:

virtual void draw() final;

Вопрос

Можно ли сделать деструктор виртуальным?

Ответ

Да. Деструктор базового класса следует объявлять виртуальным, если предполагается удалять объекты производных классов через указатель на базовый класс. Это гарантирует корректный вызов деструкторов всех уровней иерархии.


Вопрос

Что произойдёт, если деструктор базового класса не виртуальный?

Ответ

Если объект производного класса удаляется через указатель на невиртуальный деструктор базового класса, будет вызван только деструктор базового класса. Деструктор производного класса не вызовется, что приведёт к утечке ресурсов и неопределённому поведению.


Вопрос

Что такое статический и динамический тип объекта?

Ответ

Статический тип — это тип переменной, известный на этапе компиляции (например, Base*). Динамический тип — это фактический тип объекта в памяти во время выполнения (например, Derived). Виртуальные функции используют динамический тип для выбора реализации.


Исключения

Вопрос

Что такое исключения в C++?

Ответ

Исключения — это механизм обработки ошибок, позволяющий передавать информацию об аварийной ситуации из одной части программы в другую. Он основан на ключевых словах throw, try и catch.


Вопрос

Как выбрасывается исключение?

Ответ

Исключение выбрасывается с помощью оператора throw, за которым следует выражение (обычно объект):

if (x < 0) throw std::invalid_argument("x must be non-negative");

Вопрос

Как перехватывается исключение?

Ответ

Исключение перехватывается блоком catch, следующим за блоком try. Блок catch указывает тип перехватываемого исключения:

try {
riskyFunction();
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
}

Вопрос

Можно ли перехватывать исключения по значению?

Ответ

Можно, но не рекомендуется. Перехват по значению вызывает копирование объекта исключения и может привести к «срезке» (slicing), если исключение — производный класс. Лучше перехватывать по константной ссылке.


Вопрос

Что такое стек-унвиндинг (stack unwinding)?

Ответ

Стек-унвиндинг — это процесс автоматического вызова деструкторов локальных объектов при выходе из функций во время распространения исключения. Это гарантирует освобождение ресурсов даже при возникновении ошибки.


Вопрос

Что происходит, если исключение не перехвачено?

Ответ

Если исключение достигает вершины стека без перехвата, вызывается функция std::terminate, которая завершает программу.


Вопрос

Можно ли выбрасывать исключения из деструктора?

Ответ

Выбрасывание исключения из деструктора крайне нежелательно. Если деструктор вызывается во время стек-унвиндинга (уже из-за другого исключения), программа будет немедленно завершена через std::terminate.


Вопрос

Что такое спецификация исключений?

Ответ

Спецификация исключений указывает, какие исключения может выбрасывать функция. В современном C++ используется noexcept:

void func() noexcept;  // гарантирует, что не выбросит исключение

Ранние формы (throw(type)) устарели и удалены в C++17.


Вопрос

Что делает noexcept?

Ответ

noexcept указывает, что функция не выбрасывает исключений. Это позволяет компилятору применять дополнительные оптимизации. Если функция, помеченная noexcept, всё же выбросит исключение, будет вызван std::terminate.


Вопрос

Какие стандартные классы исключений есть в C++?

Ответ

Стандартная библиотека предоставляет иерархию исключений, производных от std::exception:

  • std::logic_error, std::domain_error, std::invalid_argument;
  • std::runtime_error, std::range_error, std::overflow_error;
  • std::bad_alloc (при неудаче new);
  • std::bad_cast (при неудаче dynamic_cast).

Вопрос

Что такое dynamic_cast и как он связан с исключениями?

Ответ

dynamic_cast выполняет безопасное преобразование между указателями или ссылками в иерархии наследования. При работе со ссылками, если преобразование невозможно, выбрасывается исключение std::bad_cast. При работе с указателями возвращается nullptr.


Вопрос

Что такое RAII и как он связан с исключениями?

Ответ

RAII (Resource Acquisition Is Initialization) — это идиома, при которой ресурсы (память, файлы, блокировки) привязываются к времени жизни объекта. Деструктор объекта освобождает ресурс. RAII гарантирует корректное освобождение даже при возникновении исключений.


Вопрос

Почему важно писать исключение-безопасный код?

Ответ

Исключение-безопасный код гарантирует, что состояние программы остаётся согласованным даже при возникновении исключений. Это особенно важно для контейнеров, аллокаторов и системных компонентов.


Вопрос

Что такое гарантии безопасности исключений?

Ответ

Существуют три уровня гарантий:

  • Базовая гарантия: объект остаётся в валидном, но, возможно, изменённом состоянии;
  • Сильная гарантия: операция либо полностью успешна, либо состояние не меняется (откат);
  • Гарантия без исключений: операция никогда не выбрасывает исключений (noexcept).

Вопрос

Как обеспечить сильную гарантию безопасности исключений?

Ответ

Сильная гарантия достигается с помощью идиомы «copy-and-swap»: сначала создаётся копия данных, все изменения применяются к копии, и только затем данные заменяются через обмен (swap), который не выбрасывает исключений.


Шаблоны

Вопрос

Что такое шаблон в C++?

Ответ

Шаблон — это конструкция языка, позволяющая писать обобщённый код, параметризованный типами или значениями. Шаблоны используются для создания функций и классов, работающих с любыми типами без дублирования кода.


Вопрос

Как объявить шаблон функции?

Ответ

Шаблон функции объявляется с помощью ключевого слова template, за которым следует список параметров шаблона:

template<typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}

Вопрос

В чём разница между typename и class в параметрах шаблона?

Ответ

В контексте параметров шаблона typename и class взаимозаменяемы и обозначают параметр типа. Современный стиль предпочитает typename, так как он семантически точнее.


Вопрос

Что такое специализация шаблона?

Ответ

Специализация шаблона — это предоставление альтернативной реализации шаблона для конкретного типа или набора параметров. Она позволяет оптимизировать поведение для особых случаев:

template<>
bool max<bool>(bool a, bool b) {
return a || b;
}

Вопрос

Что такое частичная специализация?

Ответ

Частичная специализация применяется только к шаблонам классов и позволяет специализировать шаблон по части его параметров. Например, можно специализировать template<typename T, typename U> только для случая, когда U = int.


Вопрос

Что такое неявное создание экземпляра шаблона?

Ответ

Когда компилятор встречает использование шаблона с конкретными аргументами, он автоматически создаёт (инстанцирует) соответствующую версию функции или класса. Это происходит во время компиляции.


Вопрос

Можно ли использовать шаблоны с не типовыми параметрами?

Ответ

Да. Параметры шаблона могут быть целочисленными константами, указателями, ссылками или перечислениями. Пример:

template<int N>
class Array {
int data[N];
};

Вопрос

Что такое auto в параметрах шаблона (C++20)?

Ответ

Начиная с C++20, можно использовать auto в параметрах шаблона для обозначения параметра, тип которого выводится из аргумента:

template<auto N>
constexpr auto value = N;

Вопрос

Что такое шаблон переменной?

Ответ

Шаблон переменной — это переменная, параметризованная типом или значением. Пример:

template<typename T>
constexpr T pi = T(3.1415926535897932385);

Вопрос

Что такое SFINAE?

Ответ

SFINAE (Substitution Failure Is Not An Error) — это правило, согласно которому ошибка подстановки аргументов шаблона не приводит к ошибке компиляции, а просто исключает эту перегрузку из рассмотрения. Это основа многих метапрограммных техник.


Стандартная библиотека (STL)

Вопрос

Что такое STL?

Ответ

STL (Standard Template Library) — это часть стандартной библиотеки C++, предоставляющая контейнеры, итераторы, алгоритмы и функциональные объекты. Все компоненты построены на шаблонах и тесно интегрированы между собой.


Вопрос

Какие основные категории контейнеров есть в STL?

Ответ

Основные категории контейнеров:

  • Последовательные: vector, deque, list, forward_list, array;
  • Ассоциативные: set, multiset, map, multimap;
  • Неупорядоченные (хэш-таблицы): unordered_set, unordered_map и их мультиверсии;
  • Контейнерные адаптеры: stack, queue, priority_queue.

Вопрос

В чём разница между vector и array?

Ответ

std::vector — динамический массив, размер которого может изменяться во время выполнения. std::array — обёртка над статическим C-массивом с фиксированным размером, заданным во время компиляции. array не выделяет память в куче.


Вопрос

Что такое итератор?

Ответ

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


Вопрос

Какие категории итераторов существуют?

Ответ

Категории итераторов:

  • Input и output — однократное чтение/запись;
  • Forward — многократное чтение вперёд;
  • Bidirectional — движение вперёд и назад;
  • Random access — произвольный доступ (как у указателей);
  • Contiguous (C++17) — элементы расположены непрерывно в памяти.

Вопрос

Что делает алгоритм std::sort?

Ответ

std::sort сортирует диапазон элементов в порядке возрастания (или по заданному компаратору). Он требует итераторы произвольного доступа и имеет среднюю сложность O(N log N).


Вопрос

Что такое лямбда-выражение в контексте STL?

Ответ

Лямбда-выражение часто используется в STL как компактный способ передачи пользовательской логики в алгоритмы:

std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; });

Вопрос

Что такое std::pair и std::tuple?

Ответ

std::pair — это шаблонный класс для хранения двух значений разных типов. std::tuple обобщает эту идею на произвольное число значений. Оба поддерживают структурированное связывание (C++17):

auto [x, y] = std::make_pair(1, 2);

Вопрос

Что такое std::move?

Ответ

std::move — это функция, которая преобразует объект в rvalue-ссылку, позволяя передать его ресурсы другому объекту через семантику перемещения. Сама по себе она не перемещает данные — она лишь меняет категорию выражения.


Вопрос

Что такое умные указатели?

Ответ

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

  • std::unique_ptr — единоличное владение;
  • std::shared_ptr — совместное владение с подсчётом ссылок;
  • std::weak_ptr — ненаблюдаемая ссылка на объект, управляемый shared_ptr.

Вопрос

В чём разница между unique_ptr и shared_ptr?

Ответ

unique_ptr обеспечивает единственное владение объектом и не допускает копирования (только перемещение). shared_ptr поддерживает несколько владельцев через счётчик ссылок и допускает копирование.


Вопрос

Что такое make_shared и make_unique?

Ответ

std::make_shared и std::make_unique — это функции для безопасного и эффективного создания умных указателей. Они предотвращают утечки при исключениях и оптимизируют выделение памяти (особенно make_shared, который выделяет объект и контрольный блок за один вызов).


Вопрос

Что такое std::string_view?

Ответ

std::string_view — это лёгкий некопирующий «вид» на строку (указатель + длина). Он позволяет передавать строки без выделения памяти и копирования, что повышает производительность.


Вопрос

Что такое std::optional?

Ответ

std::optional<T> представляет значение, которое может быть или не быть. Он безопасно заменяет использование указателей или магических значений для обозначения отсутствия результата.


Вопрос

Что такое std::variant?

Ответ

std::variant — это типобезопасный аналог объединения (union), который может хранить одно значение из заданного набора типов. Доступ к значению осуществляется через std::get или std::visit.


Управление памятью

Вопрос

Как выделяется память в C++?

Ответ

Память выделяется с помощью операторов new (для одного объекта) и new[] (для массива). Они вызывают соответствующий аллокатор и конструктор(ы). Освобождается память операторами delete и delete[].


Вопрос

В чём разница между стеком и кучей?

Ответ

Память на стеке выделяется автоматически при входе в блок и освобождается при выходе. Память в куче выделяется вручную через new и должна быть явно освобождена через delete. Объекты в куче живут дольше области видимости.


Вопрос

Что такое утечка памяти?

Ответ

Утечка памяти возникает, когда выделенная в куче память не освобождается, но теряется ссылка на неё. Это приводит к постепенному исчерпанию доступной памяти.


Вопрос

Как избежать утечек памяти?

Ответ

Утечки памяти избегаются с помощью RAII и умных указателей (unique_ptr, shared_ptr), которые автоматически освобождают память при уничтожении объекта.


Вопрос

Что такое placement new?

Ответ

Placement new — это форма оператора new, которая конструирует объект в уже выделенной области памяти. Используется в низкоуровневых библиотеках и контейнерах:

void* buffer = malloc(sizeof(MyClass));
MyClass* obj = new(buffer) MyClass();

Многопоточность (основы)

Вопрос

Какие средства многопоточности есть в стандартной библиотеке C++?

Ответ

Средства многопоточности включают:

  • std::thread — управление потоками;
  • std::mutex, std::lock_guard, std::unique_lock — синхронизация;
  • std::condition_variable — ожидание условий;
  • std::future, std::promise, std::async — асинхронные задачи.

Вопрос

Что такое гонка данных (data race)?

Ответ

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


Вопрос

Как предотвратить гонку данных?

Ответ

Гонку данных предотвращают с помощью примитивов синхронизации: мьютексы, атомарные операции (std::atomic), каналы передачи данных или проектирование без общего состояния.


Вопрос

Что делает std::lock_guard?

Ответ

std::lock_guard — это RAII-обёртка для мьютекса. Она автоматически захватывает мьютекс при создании и освобождает при уничтожении, гарантируя исключение-безопасную синхронизацию.


Вопрос

Что такое deadlock и как его избежать?

Ответ

Deadlock — это взаимная блокировка, когда два потока ожидают освобождения ресурсов, удерживаемых друг другом. Его избегают, соблюдая единый порядок захвата мьютексов, используя тайм-ауты или иерархии блокировок.


Прочие продвинутые темы

Вопрос

Что такое rvalue и lvalue?

Ответ

Lvalue — это выражение, имеющее идентификатор и адрес в памяти (например, переменная). Rvalue — временное значение без имени (например, литерал или результат функции). Rvalue можно перемещать, lvalue — копировать или перемещать явно.


Вопрос

Что такое семантика перемещения?

Ответ

Семантика перемещения позволяет передавать ресурсы от временного объекта (rvalue) новому объекту без копирования. Она реализуется через конструктор перемещения и оператор присваивания перемещением.


Вопрос

Что такое perfect forwarding?

Ответ

Perfect forwarding — это механизм передачи аргументов в другую функцию с сохранением их категории (lvalue/rvalue). Реализуется с помощью универсальных ссылок и std::forward:

template<typename T>
void wrapper(T&& arg) {
func(std::forward<T>(arg));
}

Вопрос

Что такое универсальная ссылка?

Ответ

Универсальная ссылка — это параметр шаблона вида T&&, где T выводится. Такая ссылка может быть как lvalue, так и rvalue в зависимости от переданного аргумента. Это основа perfect forwarding.


Вопрос

Что такое концепции (concepts) в C++20?

Ответ

Концепции — это ограничения на параметры шаблонов, позволяющие задавать требования к типам (например, «должен быть сравним»). Они улучшают читаемость ошибок компиляции и позволяют перегружать шаблоны по требованиям.


Вопрос

Что такое модули в C++20?

Ответ

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


Вопрос

Что такое корутины в C++20?

Ответ

Корутины — это функции, которые могут приостанавливать своё выполнение и возобновлять его позже. Они поддерживают асинхронное программирование, генераторы и ленивые вычисления.


Вопрос

Что такое constexpr в современном C++?

Ответ

constexpr указывает, что функция или переменная может быть вычислена во время компиляции, если её аргументы известны на этапе компиляции. Начиная с C++14, тело constexpr-функции может содержать почти любой код.


Вопрос

Что такое структурированное связывание (structured bindings)?

Ответ

Структурированное связывание позволяет распаковывать элементы структур, кортежей или массивов в отдельные переменные:

auto [x, y] = getPoint();

Вопрос

Какие рекомендации по современному стилю C++?

Ответ

Современный стиль C++ включает:

  • Предпочтение умных указателей вместо сырых;
  • Использование auto для упрощения кода;
  • Применение RAII для управления ресурсами;
  • Использование std::vector и std::string вместо C-массивов и char*;
  • Избегание макросов в пользу constexpr и const;
  • Использование алгоритмов STL вместо ручных циклов.