reference_wrapper
reference_wrapper - это класс-обёртка для ссылок из заголовочного файла <functional>. Он позволяет передавать ссылки как значения.
Основное преимущество в том, что reference_wrapper ведёт себя как ссылка, но может копироваться как значение. Это избавляет от необходимости использовать указатели в подобных сценариях.
В этом примере мы передаем ссылку на переменную value в функцию process, используя std::ref для создания объекта std::reference_wrapper.
В функции process мы можем работать со ссылкой, как если бы она была передана напрямую, используя метод get() для получения самой ссылки.
reference_wrapper - это класс-обёртка для ссылок из заголовочного файла <functional>. Он позволяет передавать ссылки как значения.
Основное преимущество в том, что reference_wrapper ведёт себя как ссылка, но может копироваться как значение. Это избавляет от необходимости использовать указатели в подобных сценариях.
В этом примере мы передаем ссылку на переменную value в функцию process, используя std::ref для создания объекта std::reference_wrapper.
В функции process мы можем работать со ссылкой, как если бы она была передана напрямую, используя метод get() для получения самой ссылки.
Ключевое слово const
Ключевое слово const используется для создания констант и неизменяемых объектов.
- Const для объявления переменных: запрещает изменение объекта после инициализации.
- Const указатели и ссылки: указатель или ссылка на константный объект. Нельзя изменить объект через них, только читать.
- Функции, возвращающие const значения: гарантируют, что функция не изменит объект.
- Const члены класса: нельзя изменить через объект класса.
- Const методы класса: не меняют члены класса. Часто применяются к getter-методам.
#это_база
Ключевое слово const используется для создания констант и неизменяемых объектов.
- Const для объявления переменных: запрещает изменение объекта после инициализации.
- Const указатели и ссылки: указатель или ссылка на константный объект. Нельзя изменить объект через них, только читать.
- Функции, возвращающие const значения: гарантируют, что функция не изменит объект.
- Const члены класса: нельзя изменить через объект класса.
- Const методы класса: не меняют члены класса. Часто применяются к getter-методам.
#это_база
#вопросы_с_собеседований
Что такое рефакторинг?
Рефакторинг - это процесс изменения внутренней структуры программы без изменения ее внешнего поведения.
Рефакторинг кода может применяться в следующих ситуациях:
- Улучшение читаемости и понятности кода.
- Оптимизация производительности.
- Устранение дублирования кода.
Рефакторинг особенно важен при работе над большими проектами, где код многократно изменяется и расширяется. Он позволяет поддерживать кодбейз чистым, современным и масштабируемым.
Что такое рефакторинг?
Рефакторинг кода может применяться в следующих ситуациях:
- Улучшение читаемости и понятности кода.
- Оптимизация производительности.
- Устранение дублирования кода.
Рефакторинг особенно важен при работе над большими проектами, где код многократно изменяется и расширяется. Он позволяет поддерживать кодбейз чистым, современным и масштабируемым.
std::tuple
std::tuple - это шаблонный класс, представляющий собой фиксированный набор элементов разных типов. Проще говоря, удобный инструмент для упаковки данных разных типов
Элементы tuple инициализируются в конструкторе и доступны только для чтения после создания.
tuple часто используется в комбинации с tie для присваивания кортежа переменным.
#это_база
std::tuple - это шаблонный класс, представляющий собой фиксированный набор элементов разных типов. Проще говоря, удобный инструмент для упаковки данных разных типов
Элементы tuple инициализируются в конструкторе и доступны только для чтения после создания.
tuple часто используется в комбинации с tie для присваивания кортежа переменным.
#это_база
#вопросы_с_собеседований
Что такое union?
Union - это специальный класс, который позволяет хранить данные разных типов в одной области памяти.
Основные характеристики:
- Объявляется с ключевым словом union.
- В каждый момент активно только одно поле.
- Размер равен наибольшему полю.
- Позволяет интерпретировать одну область памяти разными способами.
- Экономит память.
- Доступ к полям как в обычном классе.
Что такое union?
Основные характеристики:
- Объявляется с ключевым словом union.
- В каждый момент активно только одно поле.
- Размер равен наибольшему полю.
- Позволяет интерпретировать одну область памяти разными способами.
- Экономит память.
- Доступ к полям как в обычном классе.
msg_ptr (message pointer)
msg_ptr это указатель на структуру или класс, который содержит данные сообщения. Обычно это просто указатель void*.
Он используется в многопоточном программировании для передачи сообщений между потоками.
Использование указателей вместо копирования данных позволяет избежать лишних копий и ускорить передачу сообщений между потоками.
Если запустить код из примера, можно увидеть, что данные успешно передаются между потоками через очередь с использованием указателей на сообщения.
msg_ptr это указатель на структуру или класс, который содержит данные сообщения. Обычно это просто указатель void*.
Он используется в многопоточном программировании для передачи сообщений между потоками.
Использование указателей вместо копирования данных позволяет избежать лишних копий и ускорить передачу сообщений между потоками.
Если запустить код из примера, можно увидеть, что данные успешно передаются между потоками через очередь с использованием указателей на сообщения.
Функция before_begin()
Метод before_begin() контейнера forward_list возвращает итератор, указывающий на позицию перед первым элементом списка.
Это полезно, например, чтобы вставить элемент в начало списка.
Работает за константное время O(1), т.к. получает ссылку на начало списка.
#это_база
Метод before_begin() контейнера forward_list возвращает итератор, указывающий на позицию перед первым элементом списка.
Это полезно, например, чтобы вставить элемент в начало списка.
Работает за константное время O(1), т.к. получает ссылку на начало списка.
#это_база
try_emplace
Метод try_emplace() в C++17 - это один из способов вставки элемента в ассоциативный контейнер (например, map или unordered_map).
Позволяет вставить новый элемент по ключу, если такого ключа еще нет в контейнере.
Если ключ уже существует, то ничего не происходит.
Преимущества:
- Более эффективно, чем insert, т.к. сразу конструирует элемент на месте.
- Не делает лишних копирований или перемещений.
- Позволяет избежать ненужного перезаписывания элемента по существующему ключу.
Метод try_emplace() в C++17 - это один из способов вставки элемента в ассоциативный контейнер (например, map или unordered_map).
Позволяет вставить новый элемент по ключу, если такого ключа еще нет в контейнере.
Если ключ уже существует, то ничего не происходит.
Преимущества:
- Более эффективно, чем insert, т.к. сразу конструирует элемент на месте.
- Не делает лишних копирований или перемещений.
- Позволяет избежать ненужного перезаписывания элемента по существующему ключу.
#вопросы_с_собеседований
Почему std::make_pair больше не нужна?
В новых стандартах C++ она утратила актуальность по нескольким причинам:
— Появились инициализаторы со скобками {} для создания std::pair напрямую.
— Для вставки в контейнеры теперь есть функция emplace(), которая конструирует элемент прямо на месте.
— Можно использовать агрегатную инициализацию.
— Инициализаторы из C++17 позволяют сразу указывать ключ и значение.
Почему std::make_pair больше не нужна?
— Появились инициализаторы со скобками {} для создания std::pair напрямую.
— Для вставки в контейнеры теперь есть функция emplace(), которая конструирует элемент прямо на месте.
— Можно использовать агрегатную инициализацию.
— Инициализаторы из C++17 позволяют сразу указывать ключ и значение.
insert_or_assign
insert_or_assign — это функция из стандартной библиотеки языка C++, добавленная в C++17. Она используется для вставки элемента в ассоциативный контейнер (например, std::map) или обновления значения элемента, если ключ уже существует.
Преимущества перед operator[]:
— Более безопасна, так как проверяет существование элемента.
— Избавляет от лишнего кода для проверки наличия ключа.
insert_or_assign — это функция из стандартной библиотеки языка C++, добавленная в C++17. Она используется для вставки элемента в ассоциативный контейнер (например, std::map) или обновления значения элемента, если ключ уже существует.
Преимущества перед operator[]:
— Более безопасна, так как проверяет существование элемента.
— Избавляет от лишнего кода для проверки наличия ключа.
std::size
std::size — это функция из стандартной библиотеки C++, которая возвращает размер контейнера или массива.
Она определена в заголовочном файле <iterator>, работает со всеми стандартными контейнерами (vector, deque, list, array и др.) и с массивами всех типов, позволяя получить размер контейнера или массива в runtime.
#это_база
std::size — это функция из стандартной библиотеки C++, которая возвращает размер контейнера или массива.
Она определена в заголовочном файле <iterator>, работает со всеми стандартными контейнерами (vector, deque, list, array и др.) и с массивами всех типов, позволяя получить размер контейнера или массива в runtime.
#это_база
Атрибут nodiscard
Атрибут nodiscard — это специальный атрибут-маркер, который указывает компилятору предупреждать при игнорировании возвращаемого значения функции или метода.
Он был добавлен в С++17 для улучшения качества кода, указывается перед объявлением функции или метода и информирует компилятор, что возвращаемое значение не должно игнорироваться.
Позволяет избежать логических ошибок при игнорировании важных результатов функции.
В этом примере функция getResult() помечена атрибутом [[nodiscard]].
При вызове getResult() без использования возвращаемого значения компилятор выдаст предупреждение об игнорировании результата.
Атрибут nodiscard — это специальный атрибут-маркер, который указывает компилятору предупреждать при игнорировании возвращаемого значения функции или метода.
Он был добавлен в С++17 для улучшения качества кода, указывается перед объявлением функции или метода и информирует компилятор, что возвращаемое значение не должно игнорироваться.
Позволяет избежать логических ошибок при игнорировании важных результатов функции.
В этом примере функция getResult() помечена атрибутом [[nodiscard]].
При вызове getResult() без использования возвращаемого значения компилятор выдаст предупреждение об игнорировании результата.
Функция strrchr()
Функция strrchr(), объявленная в заголовочном файле <cstring>, ищет последнее вхождение указанного символа в строке и возвращает указатель на это вхождение.
Принимает два параметра: указатель на строку и символ для поиска, возвращает указатель на последнее вхождение символа в строке. Если символ не найден, возвращается нулевой указатель.
Полезна, когда нужно найти последнее вхождение разделителя, например точки в URL.
В примере функция strrchr() возвращает указатель на найденный символ, мы вычитаем из этого указателя начало строки, чтобы получить позицию последней точки.
#это_база
Функция strrchr(), объявленная в заголовочном файле <cstring>, ищет последнее вхождение указанного символа в строке и возвращает указатель на это вхождение.
Принимает два параметра: указатель на строку и символ для поиска, возвращает указатель на последнее вхождение символа в строке. Если символ не найден, возвращается нулевой указатель.
Полезна, когда нужно найти последнее вхождение разделителя, например точки в URL.
В примере функция strrchr() возвращает указатель на найденный символ, мы вычитаем из этого указателя начало строки, чтобы получить позицию последней точки.
#это_база
#вопросы_с_собеседований
Что такое сложность алгоритма и от чего она зависит?
Сложность алгоритма - это количественная характеристика его эффективности, которая показывает, как зависят затраты ресурсов (времени, памяти) от размера входных данных.
Сложность зависит от:
— Объема операций, которые алгоритм выполняет при обработке данных.
— Количества итераций циклов, рекурсивных вызовов.
— Зависимости числа операций от размера входных данных.
— Операций внутри вложенных циклов и структур.
Чем быстрее растёт сложность функции с ростом входных данных, тем менее эффективен алгоритм.
Что такое сложность алгоритма и от чего она зависит?
Сложность зависит от:
— Объема операций, которые алгоритм выполняет при обработке данных.
— Количества итераций циклов, рекурсивных вызовов.
— Зависимости числа операций от размера входных данных.
— Операций внутри вложенных циклов и структур.
Чем быстрее растёт сложность функции с ростом входных данных, тем менее эффективен алгоритм.
absl::btree
absl::btree — это реализация B-дерева в библиотеке Abseil для C++.
Преимущества absl::btree — это хранение данных в отсортированном порядке, быстрый поиск, вставка и удаление за O(logN), поддержка уникальных и неуникальных ключей, реализация set и map.
Применяется в задачах, где нужна высокопроизводительная структура данных с отсортированным доступом, например:
Реализация словарей и сортированных множеств;
Для хранения данных в базах данных;
В поисковых системах для индексов;
В структурах вроде кэша для быстрого доступа;
В задачах машинного обучения для хранения данных.
absl::btree — это реализация B-дерева в библиотеке Abseil для C++.
Преимущества absl::btree — это хранение данных в отсортированном порядке, быстрый поиск, вставка и удаление за O(logN), поддержка уникальных и неуникальных ключей, реализация set и map.
Применяется в задачах, где нужна высокопроизводительная структура данных с отсортированным доступом, например:
Реализация словарей и сортированных множеств;
Для хранения данных в базах данных;
В поисковых системах для индексов;
В структурах вроде кэша для быстрого доступа;
В задачах машинного обучения для хранения данных.
std::clamp
std::clamp — это функция из стандартной библиотеки, которая позволяет ограничить значение в заданном диапазоне.
Функция принимает значение, нижнюю и верхнюю границы и возвращает исходное значение, если оно входит в диапазон, или же возвращает ближайшую границу, если значение вне диапазона.
Применяется для:
— Ограничения числовых значений в заданных пределах.
— Обработки данных из недостоверных источников.
— Защиты от переполнения/обрезания данных.
— Нормализации данных в ML и компьютерном зрении.
— Реализации игровой логики в движках.
— Обработки аудио- и видео- сигналов.
std::clamp — это функция из стандартной библиотеки, которая позволяет ограничить значение в заданном диапазоне.
Функция принимает значение, нижнюю и верхнюю границы и возвращает исходное значение, если оно входит в диапазон, или же возвращает ближайшую границу, если значение вне диапазона.
Применяется для:
— Ограничения числовых значений в заданных пределах.
— Обработки данных из недостоверных источников.
— Защиты от переполнения/обрезания данных.
— Нормализации данных в ML и компьютерном зрении.
— Реализации игровой логики в движках.
— Обработки аудио- и видео- сигналов.
Алгоритм generate
std::generate — это алгоритм из стандартной библиотеки C++, который используется для заполнения диапазона элементов сгенерированными значениями.
Принимает три параметра: начало диапазона, конец диапазона и функцию генерации. Функция генерации должна принимать неявный счетчик и возвращать очередное значение.
Для каждого элемента в заданном диапазоне будет вызываться функция генерации, и результат будет записан в этот элемент.
В этом примере std::generate совместно с генератором случайных чисел используется для быстрого заполнения вектора случайными значениями.
#это_база
std::generate — это алгоритм из стандартной библиотеки C++, который используется для заполнения диапазона элементов сгенерированными значениями.
Принимает три параметра: начало диапазона, конец диапазона и функцию генерации. Функция генерации должна принимать неявный счетчик и возвращать очередное значение.
Для каждого элемента в заданном диапазоне будет вызываться функция генерации, и результат будет записан в этот элемент.
В этом примере std::generate совместно с генератором случайных чисел используется для быстрого заполнения вектора случайными значениями.
#это_база
#вопросы_с_собеседований
Может ли inline-функция быть рекурсивной?
Поскольку компилятор просто встраивает код inline-функции в место вызова, не имеет значения, является ли эта функция рекурсивной или нет. Компилятор будет просто копировать один и тот же код функции при каждом рекурсивном вызове.
Таким образом, рекурсивные inline-функции абсолютно допустимы и часто используются, когда нужна рекурсия без накладных расходов на стандартные вызовы функций.
Может ли inline-функция быть рекурсивной?
Таким образом, рекурсивные inline-функции абсолютно допустимы и часто используются, когда нужна рекурсия без накладных расходов на стандартные вызовы функций.
#вопросы_с_собеседований
Для чего нужен атрибут fallthrough?
Атрибут [[fallthrough]] используется для явного указания того, что в конструкции switch нужно пропустить break в конце case и перейти к выполнению следующего case.
По умолчанию в С++17 и новее переход между case без break приводит к ошибке компиляции и чтобы сохранить старое поведение и разрешить переход, нужно добавить [[fallthrough]].
Это улучшает читаемость кода, явно указывая на отсутствие break и помогает избежать случайного отсутствия break, когда разработчик забыл его добавить.
[[fallthrough]] также полезен при рефакторинге старого кода с switch в современный стандарт С++.
Для чего нужен атрибут fallthrough?
По умолчанию в С++17 и новее переход между case без break приводит к ошибке компиляции и чтобы сохранить старое поведение и разрешить переход, нужно добавить [[fallthrough]].
Это улучшает читаемость кода, явно указывая на отсутствие break и помогает избежать случайного отсутствия break, когда разработчик забыл его добавить.
[[fallthrough]] также полезен при рефакторинге старого кода с switch в современный стандарт С++.
#вопросы_с_собеседований
Для чего нужен атрибут maybe_unused?
Атрибут [[maybe_unused]] используется для подавления предупреждений компилятора об неиспользуемых объектах.
Компилятор выдает предупреждение, если объект объявлен, но нигде не используется и чтобы избавиться от ложных предупреждений, например, когда объект используется только в отладочной сборке, применяют [[maybe_unused]].
Позволяет задать политику использования на уровне отдельных объектов и улучшает читаемость кода, явно объясняя причину неиспользования.
Для чего нужен атрибут maybe_unused?
Компилятор выдает предупреждение, если объект объявлен, но нигде не используется и чтобы избавиться от ложных предупреждений, например, когда объект используется только в отладочной сборке, применяют [[maybe_unused]].
Позволяет задать политику использования на уровне отдельных объектов и улучшает читаемость кода, явно объясняя причину неиспользования.
Лямбда-выражения
Лямбда-выражения (lambda) — это безымянные функции, которые можно использовать для передачи поведения или сравнения.
Объявляются как {body;}, в квадратных скобках указываются аргументы, в фигурных — тело.
Полезны для задания функций сравнения, например в алгоритмах sort(), когда нужно быстро передать функциональность, не создавая отдельную функцию.
Поддерживают захват по значению [=] и по ссылке [&].
Можно сохранить в переменной с помощью auto.
#это_база
Лямбда-выражения (lambda) — это безымянные функции, которые можно использовать для передачи поведения или сравнения.
Объявляются как {body;}, в квадратных скобках указываются аргументы, в фигурных — тело.
Полезны для задания функций сравнения, например в алгоритмах sort(), когда нужно быстро передать функциональность, не создавая отдельную функцию.
Поддерживают захват по значению [=] и по ссылке [&].
Можно сохранить в переменной с помощью auto.
#это_база