Современные возможности C++ и проверенные паттерны: активный объект, внешний полиморфизм и корутины
В этой статье автор показывает, как внешний полиморфизм (реализация полиморфного поведения вне объекта, для которого такое поведение требуется) помогает писать красивые и чистые программы, и рассказывает о некоторых базовых и продвинутых способах реализации.
Смотреть статью
В этой статье автор показывает, как внешний полиморфизм (реализация полиморфного поведения вне объекта, для которого такое поведение требуется) помогает писать красивые и чистые программы, и рассказывает о некоторых базовых и продвинутых способах реализации.
Смотреть статью
Автоматический вывод типа аргумента шаблона класса
Выглядит название этой возможности довольно длинным и сложным, но на самом деле ничего сложного тут нет. Основная идея в том, что в C++17 вывод типов аргументов шаблонов выполняется и для стандартных шаблонов классов. Ранее это поддерживалось лишь для функциональных шаблонов. В результате оказывается, что раньше писали так:
С выходом C++ 17 эту конструкцию стало можно заменить на эту:
Вывод типов выполняется неявно. Этим механизмом ещё удобнее пользоваться в том случае, когда речь идёт о кортежах. А именно, раньше приходилось писать следующее:
Теперь же то же самое выглядит так:
Тут стоит отметить, что эти возможности не покажутся чем-то достойным внимания тем, кто не особенно хорошо знаком с шаблонами C++.
Выглядит название этой возможности довольно длинным и сложным, но на самом деле ничего сложного тут нет. Основная идея в том, что в C++17 вывод типов аргументов шаблонов выполняется и для стандартных шаблонов классов. Ранее это поддерживалось лишь для функциональных шаблонов. В результате оказывается, что раньше писали так:
std::pair<std::string, int> user = {"M", 25};
С выходом C++ 17 эту конструкцию стало можно заменить на эту:
std::pair user = {"M", 25};
Вывод типов выполняется неявно. Этим механизмом ещё удобнее пользоваться в том случае, когда речь идёт о кортежах. А именно, раньше приходилось писать следующее:
std::tuple<std::string, std::string, int> user ("M", "Chy", 25);
Теперь же то же самое выглядит так:
std::tuple user2("M", "Chy", 25);
Тут стоит отметить, что эти возможности не покажутся чем-то достойным внимания тем, кто не особенно хорошо знаком с шаблонами C++.
#вопросы_с_собеседований
Виртуальный конструктор: что он собой представляет?
Ответ:
Это каверзный вопрос с IT-собеседований, который чаще всего задают после виртуальных деструкторов, чтобы запутать. Конструктор не может быть виртуальным, поскольку в этом нет никакого смысла: при создании объектов нет такой неоднозначности, как при их удалении. 😁
Виртуальный конструктор: что он собой представляет?
Ответ:
Это
Быстрая сортировка
Отсортируйте заданный массив с помощью быстрой сортировки.
Формат входных данных:
Первая строка входных данных содержит одно натуральное число nn (1 ≤ n ≤ 10^5) – количество элементов в массиве. В следующей строке находятся элементы массива – n целых чисел, не превосходящих по абсолютной величине 10^9.
Формат выходных данных:
Выведите элементы массива в порядке неубывания.
Отсортируйте заданный массив с помощью быстрой сортировки.
Формат входных данных:
Первая строка входных данных содержит одно натуральное число nn (1 ≤ n ≤ 10^5) – количество элементов в массиве. В следующей строке находятся элементы массива – n целых чисел, не превосходящих по абсолютной величине 10^9.
Формат выходных данных:
Выведите элементы массива в порядке неубывания.
#вопросы_с_собеседований
Что лучше: const или define?
Ответ:
define - это директива препроцессора, которая не учитывает ни типов, ни областей видимости. Препроцессор вставляет значение везде, где оно используется и создается множество копий 3.14159265359 в объектном коде, константа никогда не порождает больше одной копии этого значения. define трудно отлаживать, потому что у него нет имени, только магическое число, нельзя взять адрес или создать ссылку на это значение.
У const есть тип, область видимости, можно взять адрес, создать константную ссылку на эту переменную.
Определенно, лучше использовать const, а не define.
Что лучше: const или define?
Ответ:
У const есть тип, область видимости, можно взять адрес, создать константную ссылку на эту переменную.
Определенно, лучше использовать const, а не define.
#вопросы_с_собеседований
Что быстрее: постфиксные инкрементные операторы или префиксные? Чем отличается их сигнатура?
Префиксные операторы быстрее. В постфиксных операторах производится дополнительная операция сохранения предыдущего состояния объекта, а затем только увеличение на 1, а в префиксном операторе после инкрементирования объекта, сразу возвращается ссылка объект.
Сигнатура их отличается фиктивным параметром int у постфиксного оператора.
Что быстрее: постфиксные инкрементные операторы или префиксные? Чем отличается их сигнатура?
Префиксные операторы быстрее. В постфиксных операторах производится дополнительная операция сохранения предыдущего состояния объекта, а затем только увеличение на 1, а в префиксном операторе после инкрементирования объекта, сразу возвращается ссылка объект.
Сигнатура их отличается фиктивным параметром int у постфиксного оператора.
#вопросы_с_собеседований
Какие отличия у std::array и std::vector?
std::array — это обёртка вокруг обычного массива, фиксированного размера, а std::vector - это динамически расширяемый массив. std::array хранит свои данные в стековой памяти, а vector выделяет память в куче (динамическая память). У std::array в параметрах шаблона указывается тип хранимых элементов и размер массива. А у std::vector - тип элементов и ещё возможно указать аллокатор, который нужно использовать при выделении памяти (с помощью new). std::array чуть лучше по производительности в случае небольшого массива, чем std::vector, который содержит в себе несколько указателей, которые указывают на выделенный в куче кусок памяти.
Какие отличия у std::array и std::vector?
#вопросы_с_собеседований
Может ли inline-функция быть рекурсивной?
Поскольку компилятор просто встраивает код inline-функции в место вызова, не имеет значения, является ли эта функция рекурсивной или нет. Компилятор будет просто копировать один и тот же код функции при каждом рекурсивном вызове.
Таким образом, рекурсивные inline-функции абсолютно допустимы и часто используются, когда нужна рекурсия без накладных расходов на стандартные вызовы функций.
Может ли inline-функция быть рекурсивной?
Таким образом, рекурсивные inline-функции абсолютно допустимы и часто используются, когда нужна рекурсия без накладных расходов на стандартные вызовы функций.
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::flat_map
для оптимизации производительностиstd::flat_map
— это структура данных, которая представляет собой ассоциативный контейнер, хранящий пары "ключ-значение" в упорядоченном виде с использованием вектора.В отличие от
std::map
, std::flat_map
оптимизирован для случаев, когда количество элементов невелико, так как хранение данных в последовательной области памяти снижает накладные расходы и улучшает кэширование.• std::flat_map
полезен для приложений, где требуется высокая производительность при небольших объемах данных и частых поисках.Please open Telegram to view this post
VIEW IN TELEGRAM
Как работает Rule of Five в C++ и когда его следует применять?
Ответ
Please open Telegram to view this post
VIEW IN TELEGRAM
std::latch
для синхронизации потоковstd::latch
— это примитив синхронизации, который позволяет одному или нескольким потокам ожидать, пока другие потоки не завершат выполнение. В отличие от std::barrier
, он не перезагружается после достижения условия синхронизации, что делает его полезным для одноразовой координации.std::latch
полезен в ситуациях, когда необходимо, чтобы один поток ждал завершения других потоков.Please open Telegram to view this post
VIEW IN TELEGRAM
cppcoro — это библиотека, предоставляющая набор инструментов для работы с корутинами в C++, включая асинхронные операции, таймеры, семафоры и другие примитивы синхронизации. Это упрощает написание асинхронного кода с поддержкой корутин, обеспечивая высокую производительность и читаемость.
•
cppcoro — отличный выбор для создания высокопроизводительных асинхронных приложений с использованием корутин.Please open Telegram to view this post
VIEW IN TELEGRAM
async_simple — это новая библиотека, которая предоставляет простой и эффективный способ работы с асинхронными операциями в C++. Она упрощает управление асинхронными задачами, улучшая читабельность и производительность кода.
•
async_simple идеально подходит для тех, кто хочет писать асинхронный код без сложных шаблонов и лишних зависимостей.Please open Telegram to view this post
VIEW IN TELEGRAM
EnTT — это мощная библиотека для создания игр и симуляций с использованием паттерна Entity-Component-System (ECS).
Она позволяет легко управлять большими наборами объектов (сущностей) и их компонентами, что делает её отличным выбором для разработки игровых приложений и других систем, где важна масштабируемость и производительность.
•
EnTT — отличный инструмент для разработчиков, создающих сложные игровые системы или симуляции с большим количеством взаимодействующих объектов.Please open Telegram to view this post
VIEW IN TELEGRAM
di — это легковесная библиотека для управления зависимостями в C++. Она предоставляет простой способ внедрения зависимостей, что делает код более модульным и тестируемым.
•
di поддерживает автоматическое создание зависимостей и упрощает управление компонентами в сложных проектах.Please open Telegram to view this post
VIEW IN TELEGRAM
magic_enum — это современная библиотека для C++, которая предоставляет возможности рефлексии для перечислений (enum). Она позволяет легко преобразовывать значения перечислений в строки и обратно, а также получать список всех значений перечисления.
•
magic_enum упрощает работу с перечислениями, улучшая читаемость и безопасность кода.Please open Telegram to view this post
VIEW IN TELEGRAM
Outcome — это библиотека для удобной работы с обработкой ошибок в C++. Она предоставляет гибкий механизм для возврата и обработки ошибок без использования исключений, что улучшает производительность и делает код более предсказуемым.
•
Outcome позволяет возвращать и обрабатывать значения ошибок с минимальными накладными расходами.Please open Telegram to view this post
VIEW IN TELEGRAM
SML — это библиотека для создания конечных автоматов с высокой производительностью и минимальной затратой на компиляцию. Она помогает моделировать сложные состояния и переходы.
Please open Telegram to view this post
VIEW IN TELEGRAM