static_assert
static_assert — это механизм проверки условий компиляции. Он позволяет выдавать ошибку компиляции, если не выполняется некое условие.
Основные случаи использования:
— Проверка размера типов данных.
— Проверка наличия функций или методов у классов.
— Верификация определенных свойств на этапе компиляции.
— Проверка корректности шаблонных параметров.
— Выявление ошибок в зависимостях между типами данных.
Преимущества:
— Выявляет ошибки на этапе компиляции, не дожидаясь выполнения.
— Позволяет проверить условия, которые нельзя проверить во время выполнения.
— Улучшает читаемость кода за счет явных проверок.
static_assert широко используется в шаблонах и метапрограммировании.
static_assert — это механизм проверки условий компиляции. Он позволяет выдавать ошибку компиляции, если не выполняется некое условие.
Основные случаи использования:
— Проверка размера типов данных.
— Проверка наличия функций или методов у классов.
— Верификация определенных свойств на этапе компиляции.
— Проверка корректности шаблонных параметров.
— Выявление ошибок в зависимостях между типами данных.
Преимущества:
— Выявляет ошибки на этапе компиляции, не дожидаясь выполнения.
— Позволяет проверить условия, которые нельзя проверить во время выполнения.
— Улучшает читаемость кода за счет явных проверок.
static_assert широко используется в шаблонах и метапрограммировании.
#вопросы_с_собеседований
Расскажите о работе с сырыми указателями.
Работа с сырыми указателями (raw pointers) требует внимания к управлению памятью:
— Сырой указатель содержит только адрес памяти, без информации о длительности владения.
— Память под указатель выделяется вручную с помощью new и освобождается вручную с delete.
— Опасность утечек памяти при потере последнего указателя на объект.
— Нужно следить за правильностью вызовов new/delete во избежание ошибок.
— Может привести к проблемам при копировании указателей (неявное копирование объекта).
— Предпочтительно использовать умные указатели вроде unique_ptr для безопасности.
— Сырые указатели полезны для низкоуровневых оптимизаций производительности.
— Требуют явного кодирования работы с памятью в стиле Си.
Расскажите о работе с сырыми указателями.
— Сырой указатель содержит только адрес памяти, без информации о длительности владения.
— Память под указатель выделяется вручную с помощью new и освобождается вручную с delete.
— Опасность утечек памяти при потере последнего указателя на объект.
— Нужно следить за правильностью вызовов new/delete во избежание ошибок.
— Может привести к проблемам при копировании указателей (неявное копирование объекта).
— Предпочтительно использовать умные указатели вроде unique_ptr для безопасности.
— Сырые указатели полезны для низкоуровневых оптимизаций производительности.
— Требуют явного кодирования работы с памятью в стиле Си.
#вопросы_с_собеседований
Расскажите об использовании realloc в контейнерах.
realloc используется в контейнерах динамической памяти, таких как vector, для изменения выделенной памяти при добавлении или удалении элементов.
realloc вызывается при заполнении текущего буфера в контейнере и память перевыделяется большими блоками (обычно в 2 раза больше). Это позволяет избежать постоянного выделения памяти заново.
Само перевыделение происходит автоматически, скрыто от разработчика.
При частых вызовах может привести к фрагментации памяти.
Расскажите об использовании realloc в контейнерах.
realloc вызывается при заполнении текущего буфера в контейнере и память перевыделяется большими блоками (обычно в 2 раза больше). Это позволяет избежать постоянного выделения памяти заново.
Само перевыделение происходит автоматически, скрыто от разработчика.
При частых вызовах может привести к фрагментации памяти.
Алгоритм equal_range
equal_range — это алгоритм поиска из стандартной библиотеки, который находит диапазон элементов, эквивалентных заданному значению.
Принимает отсортированный диапазон, искомое значение и возвращает пару итераторов, задающих найденный диапазон.
Диапазон содержит все элементы, эквивалентные значению. Если элементов нет — итераторы будут указывать на один элемент.
Применение:
— Поиск всех элементов, соответствующих значению.
— Получение диапазона для последующей обработки.
— Высокоэффективная альтернатива линейному поиску.
#это_база
equal_range — это алгоритм поиска из стандартной библиотеки, который находит диапазон элементов, эквивалентных заданному значению.
Принимает отсортированный диапазон, искомое значение и возвращает пару итераторов, задающих найденный диапазон.
Диапазон содержит все элементы, эквивалентные значению. Если элементов нет — итераторы будут указывать на один элемент.
Применение:
— Поиск всех элементов, соответствующих значению.
— Получение диапазона для последующей обработки.
— Высокоэффективная альтернатива линейному поиску.
#это_база
Алгоритм partial_sort
partial_sort — это алгоритм сортировки из стандартной библиотеки, который упорядочивает только часть контейнера.
Сортирует элементы в диапазоне [first, middle). Элементы справа от middle остаются без изменений
При работе с частью данных эффективнее полной сортировки. Внутри использует алгоритм quicksort.
Применение:
— Быстрый поиск K наибольших/наименьших элементов.
— Сортировка только части большого массива данных.
— Оптимизация производительности по сравнению с полной сортировкой.
#это_база
partial_sort — это алгоритм сортировки из стандартной библиотеки, который упорядочивает только часть контейнера.
Сортирует элементы в диапазоне [first, middle). Элементы справа от middle остаются без изменений
При работе с частью данных эффективнее полной сортировки. Внутри использует алгоритм quicksort.
Применение:
— Быстрый поиск K наибольших/наименьших элементов.
— Сортировка только части большого массива данных.
— Оптимизация производительности по сравнению с полной сортировкой.
#это_база
#вопросы_с_собеседований
Что такое SIMD-инструкции?
SIMD-инструкции — это специальные команды процессора, которые работают с векторными регистрами и могут выполнять одну операцию над несколькими элементами данных параллельно.
Например, при сложении двух векторов из 4 float чисел, вместо 4 инструкций сложения, с SIMD можно выполнить одну команду, которая сложит эти вектора за одну операцию.
Основные преимущества SIMD:
— Повышение производительности за счет параллельных вычислений.
— Эффективное использование пропускной способности процессора.
— Уменьшение количества инструкций за счет векторизации.
— Оптимизация алгоритмов обработки массивов, матриц, фильтрации, графики.
Что такое SIMD-инструкции?
Например, при сложении двух векторов из 4 float чисел, вместо 4 инструкций сложения, с SIMD можно выполнить одну команду, которая сложит эти вектора за одну операцию.
Основные преимущества SIMD:
— Повышение производительности за счет параллельных вычислений.
— Эффективное использование пропускной способности процессора.
— Уменьшение количества инструкций за счет векторизации.
— Оптимизация алгоритмов обработки массивов, матриц, фильтрации, графики.
#вопросы_с_собеседований
Что такое variadic templates?
Variadic templates — это функция шаблонов, которая позволяет определить функцию или класс с переменным количеством аргументов.
Эта возможность появилась в C++11.
Variadic templates позволяют создавать функции, которые могут принимать произвольное количество аргументов, не зная заранее их типов.
Это достигается за счет использования упаковки аргументов (pack expansion) и рекурсивных шаблонов.
Проще говоря, variadic templates расширяют возможности шаблонов и позволяют создавать гибкие и универсальные компоненты.
Что такое variadic templates?
Эта возможность появилась в C++11.
Variadic templates позволяют создавать функции, которые могут принимать произвольное количество аргументов, не зная заранее их типов.
Это достигается за счет использования упаковки аргументов (pack expansion) и рекурсивных шаблонов.
Проще говоря, variadic templates расширяют возможности шаблонов и позволяют создавать гибкие и универсальные компоненты.
This media is not supported in your browser
VIEW IN TELEGRAM
Плюсовики, отмечаем 2 августа в календаре: Яндекс проведет C++ Zero Cost Conf
Участников ждет прикладной C++ и десятки докладов от экспертов из Яндекса, Ozon, VK, Авито и других компаний. Конференция пройдет в трёх городах — Москве, Санкт-Петербурге и Белграде.
В Санкт-Петербурге Ваня Ходор, руководитель бэкенда каталога в
Яндекс Лавке, выступит с докладом на тему «i, j, k и шаблоны: вспоминаем линейную алгебру». Там же разработчики из VK, Кирилл Гарманов и Илья Кокорин, расскажут, с какими проблемами специалисты сталкиваются, когда пишут конкурентные структуры данных и как значительно облегчить боль от проверки и отладки конкурентного кода.
В Москве Антон Полухин, руководитель группы разработки общих компонентов в Техплатформе Городских сервисов Яндекса, расскажет, как использовать C++20 модули в больших существующих проектах с поддержкой старых стандартов.
Посмотреть полную программу докладов во всех городах и зарегистрироваться можно на сайте конференции.
Участников ждет прикладной C++ и десятки докладов от экспертов из Яндекса, Ozon, VK, Авито и других компаний. Конференция пройдет в трёх городах — Москве, Санкт-Петербурге и Белграде.
В Санкт-Петербурге Ваня Ходор, руководитель бэкенда каталога в
Яндекс Лавке, выступит с докладом на тему «i, j, k и шаблоны: вспоминаем линейную алгебру». Там же разработчики из VK, Кирилл Гарманов и Илья Кокорин, расскажут, с какими проблемами специалисты сталкиваются, когда пишут конкурентные структуры данных и как значительно облегчить боль от проверки и отладки конкурентного кода.
В Москве Антон Полухин, руководитель группы разработки общих компонентов в Техплатформе Городских сервисов Яндекса, расскажет, как использовать C++20 модули в больших существующих проектах с поддержкой старых стандартов.
Посмотреть полную программу докладов во всех городах и зарегистрироваться можно на сайте конференции.
Ромбовидное наследование
Ромбовидное наследование (diamond inheritance) — это ситуация, когда класс наследуется от нескольких базовых классов, которые в свою очередь наследуются от общего предка.
Например:
На изображении класс
При вызове
Ромбовидное наследование (diamond inheritance) — это ситуация, когда класс наследуется от нескольких базовых классов, которые в свою очередь наследуются от общего предка.
Например:
class A { };Здесь класс
class B : public A { };
class C : public A { };
class D : public B, public C { };
D
наследуется от B
и C
, которые оба наследуются от класса A
. Получается ромбовидная иерархия наследования.На изображении класс
D
наследуется от B
и C
, которые в свою очередь наследуют метод print()
от A
.При вызове
printAll()
метод print()
вызывается дважды — по пути наследования через B
и через C
.Алгоритм stable_partition
Алгоритм
Он принимает начало и конец контейнера, а также условие в виде функции или лямбда-выражения.
В результате все элементы, для которых условие истинно, окажутся в начале контейнера, а остальные — в конце.
Отличие от
Это бывает важно, например, при разбиении по нескольким критериям.
В примере мы разделили вектор на две части — четные и нечетные числа. Благодаря
#это_база
Алгоритм
std::stable_partition
используется для разбиения контейнера на две части по какому-либо условию. Он принимает начало и конец контейнера, а также условие в виде функции или лямбда-выражения.
В результате все элементы, для которых условие истинно, окажутся в начале контейнера, а остальные — в конце.
Отличие от
partition
в том, что stable_partition
сохраняет относительный порядок элементов. Те, что шли перед разбиением в одной группе, останутся в том же порядке после.Это бывает важно, например, при разбиении по нескольким критериям.
В примере мы разделили вектор на две части — четные и нечетные числа. Благодаря
stable_partition
сохранен относительный порядок элементов в каждой части.#это_база
Функция resize
Функция
Она динамически меняет количество элементов в контейнере на указанное число.
Например, для вектора
Если изначально элементов было меньше — новые будут инициализированы по умолчанию (нулями). Если было больше — лишние удалятся.
Также можно явно задать значение для инициализации:
#это_база
Функция
resize
служит для изменения размера контейнеров, например вектора или deque
. Она динамически меняет количество элементов в контейнере на указанное число.
Например, для вектора
numbers
вызов:numbers.resize(100);Установит размер вектора в 100 элементов.
Если изначально элементов было меньше — новые будут инициализированы по умолчанию (нулями). Если было больше — лишние удалятся.
Также можно явно задать значение для инициализации:
numbers.resize(80, -1);Также
resize
принимает вектор-шаблон для копирования значений при расширении.#это_база
Немного про метапрограммирование и эстетическое удовольствие от type_traits
Сегодня прочитал пост Вани Ходора (бэкенд-разраб из Лавки) про type traits — небольшой гайд, который наверняка вызовет ностальгию у тех, кто когда-то лепил свои std::enable_if, is_same, remove_cvref, потому что библиотека ещё была до C++14 и приходилось всё тащить на себе.
Казалось бы, type_traits — довольно скучная часть стандартной библиотеки. Но чем больше работаешь с шаблонным кодом, тем чаще ловишь себя на том, что это не просто утилиты, а строительные блоки для архитектуры. И да, некоторые из них прямо эстетически красивые.
Из любимого — std::is_invocable, std::is_detected, std::conditional_t, std::void_t. Когда видишь, как эти трейты могут элегантно разрулить перегрузку, или сделать fallback на дефолтную реализацию без лишних ифов — это как хорошо написанная лямбда: вроде ничего особенного, а работает идеально.
Интересно, что в посте Ваня делает именно то, чего часто не хватает в серьезных разборках: он просто делится тем, что ему нравится. Это похоже на разговор с коллегой на кухне, когда ты не лекцию читаешь, а делишься любимыми инструментами.
В целом, type_traits — это, по сути, DSL на минималках. Если подходить к ним не как к синтаксическому сахару, а как к способу выразить правила типов прямо в коде — открывается совсем другой уровень выразительности. Особенно если ты пишешь свои обёртки, декораторы или generic-компоненты.
👴 Помню времена, когда std::enable_if приходилось объяснять джунам с доской и маркером. Сейчас это уже почти common sense. И это хорошо — потому что без этой базы метапрограммировать тяжело.
В общем, рекомендую почитать — вдруг тоже вспомните свои любимые трейты. А если нет — повод попробовать std::is_aggregate или std::is_trivially_copyable и посмотреть, как они могут облегчить жизнь.
Кстати, а у вас в команде кто-нибудь ещё пишет свои трейты или все уже перешли на концепты?
Сегодня прочитал пост Вани Ходора (бэкенд-разраб из Лавки) про type traits — небольшой гайд, который наверняка вызовет ностальгию у тех, кто когда-то лепил свои std::enable_if, is_same, remove_cvref, потому что библиотека ещё была до C++14 и приходилось всё тащить на себе.
Казалось бы, type_traits — довольно скучная часть стандартной библиотеки. Но чем больше работаешь с шаблонным кодом, тем чаще ловишь себя на том, что это не просто утилиты, а строительные блоки для архитектуры. И да, некоторые из них прямо эстетически красивые.
Из любимого — std::is_invocable, std::is_detected, std::conditional_t, std::void_t. Когда видишь, как эти трейты могут элегантно разрулить перегрузку, или сделать fallback на дефолтную реализацию без лишних ифов — это как хорошо написанная лямбда: вроде ничего особенного, а работает идеально.
Интересно, что в посте Ваня делает именно то, чего часто не хватает в серьезных разборках: он просто делится тем, что ему нравится. Это похоже на разговор с коллегой на кухне, когда ты не лекцию читаешь, а делишься любимыми инструментами.
В целом, type_traits — это, по сути, DSL на минималках. Если подходить к ним не как к синтаксическому сахару, а как к способу выразить правила типов прямо в коде — открывается совсем другой уровень выразительности. Особенно если ты пишешь свои обёртки, декораторы или generic-компоненты.
👴 Помню времена, когда std::enable_if приходилось объяснять джунам с доской и маркером. Сейчас это уже почти common sense. И это хорошо — потому что без этой базы метапрограммировать тяжело.
В общем, рекомендую почитать — вдруг тоже вспомните свои любимые трейты. А если нет — повод попробовать std::is_aggregate или std::is_trivially_copyable и посмотреть, как они могут облегчить жизнь.
Кстати, а у вас в команде кто-нибудь ещё пишет свои трейты или все уже перешли на концепты?
Telegraph
Микрогайд по type_traits
<type_traits> -- хедер стандартной библиотеки, являющийся частью библиотеки для метапрограммирования. Я не буду вам пояснять принципы работы тех или иных трейтов. Мы не будем разбираться в том, что такое using, наследование, как выбирается специализация…
#вопросы_с_собеседований
Как подсчитать количество элементов в std::list?
Чтобы подсчитать количество элементов в std::list, можно использовать следующие способы:
1. Вызвать метод size() самого списка. Он вернет количество элементов.
2. Проитерировать список циклом и считать элементы.
3. Воспользоваться алгоритмом std::distance, передав ему начало и конец списка.
4. Применить алгоритм std::count_if с условием, которое всегда истинно.
Как подсчитать количество элементов в std::list?
1. Вызвать метод size() самого списка. Он вернет количество элементов.
2. Проитерировать список циклом и считать элементы.
3. Воспользоваться алгоритмом std::distance, передав ему начало и конец списка.
4. Применить алгоритм std::count_if с условием, которое всегда истинно.
spaceship operator
Spaceship operator (<=>) — это оператор сравнения, введенный в C++20.
Преимущества spaceship operator:
— Позволяет создавать типы, которые можно сравнивать с помощью одного оператора вместо нескольких (==, !=, <, > и т. д.).
— Упрощает написание функций сравнения, например
— Читабельнее и компактнее кода с традиционными операторами сравнения.
Spaceship operator (<=>) — это оператор сравнения, введенный в C++20.
Преимущества spaceship operator:
— Позволяет создавать типы, которые можно сравнивать с помощью одного оператора вместо нескольких (==, !=, <, > и т. д.).
— Упрощает написание функций сравнения, например
std::sort
.— Читабельнее и компактнее кода с традиционными операторами сравнения.
#вопросы_с_собеседований
Что случится, если вернуть ссылку на временный объект?
Если вернуть ссылку на временный объект, созданный в стеке, то это приведет к неопределенному поведению программы.
После выхода из функции память, выделенная под временный объект, освобождается. И если где-то сохранилась ссылка на этот объект, то при попытке обратиться к нему произойдет ошибка.
Что случится, если вернуть ссылку на временный объект?
После выхода из функции память, выделенная под временный объект, освобождается. И если где-то сохранилась ссылка на этот объект, то при попытке обратиться к нему произойдет ошибка.
Концепт IterToComparable
Концепт IterToComparable появился в стандарте C++20 и используется для проверки того, что итератор указывает на объекты, которые можно сравнивать.
Этот концепт позволяет убедиться, что можно сравнивать объекты, на которые ссылается итератор, с помощью операторов сравнения как
В примере используется концепт
Концепт IterToComparable появился в стандарте C++20 и используется для проверки того, что итератор указывает на объекты, которые можно сравнивать.
Этот концепт позволяет убедиться, что можно сравнивать объекты, на которые ссылается итератор, с помощью операторов сравнения как
<
, <=
, >
, >=
.В примере используется концепт
iter_to_comparable
для проверки, что итератор по std::vector
указывает на сравнимые объекты int
. Это позволяет корректно найти минимальный элемент с помощью std::min_element
.Библиотека концепций
Библиотека концепций — это набор функций и классов, которые позволяют определять и проверять концепции. Концепция — это набор логических предикатов, которые определяют свойства типа или выражения. Концепции могут использоваться для проверки типов параметров шаблонов, определения совместимости типов и повышения безопасности и надежности кода.
Библиотека концепций была введена в стандарт C++ 20. Она основана на концепциих Boost, которые были реализованы в библиотеке Boost еще в 2005 году.
#для_продвинутых
Библиотека концепций — это набор функций и классов, которые позволяют определять и проверять концепции. Концепция — это набор логических предикатов, которые определяют свойства типа или выражения. Концепции могут использоваться для проверки типов параметров шаблонов, определения совместимости типов и повышения безопасности и надежности кода.
Библиотека концепций была введена в стандарт C++ 20. Она основана на концепциих Boost, которые были реализованы в библиотеке Boost еще в 2005 году.
#для_продвинутых
Media is too big
VIEW IN TELEGRAM
🚀 YADRO приглашает C++ разработчиков в команду OpenBMC и встроенных систем!
Если вы хотите создавать сложное программное обеспечение для серверов и систем хранения данных, работать с передовыми технологиями Linux и участвовать в проектах open source, то эта возможность для вас.
📌 Кого мы ищем:
• Ведущего разработчика C++ (Linux/OpenBMC)
• Ведущего разработчика интерфейсов встроенных систем
• TeamLead разработки OpenBMC
🧰 Технологический стек и задачи:
• C++ (стандарты 17, 20, 23), STL, Boost
• Linux-среда, systemd, D-Bus, Yocto, bash, Python
• Работа с ядром прошивки OpenBMC, взаимодействие с UEFI/BIOS
• Разработка и поддержка сложных интерфейсов встроенных систем
💼 Условия работы:
• Гибкий формат: удалённо или в офисах в Москве, Санкт-Петербурге, Екатеринбурге, Нижнем Новгороде и Минске
• Работа с масштабными проектами в уникальной команде инженеров
• Возможность горизонтального и вертикального карьерного роста
💙 Узнайте больше и откликайтесь на вакансии прямо на сайте!
Если вы хотите создавать сложное программное обеспечение для серверов и систем хранения данных, работать с передовыми технологиями Linux и участвовать в проектах open source, то эта возможность для вас.
📌 Кого мы ищем:
• Ведущего разработчика C++ (Linux/OpenBMC)
• Ведущего разработчика интерфейсов встроенных систем
• TeamLead разработки OpenBMC
🧰 Технологический стек и задачи:
• C++ (стандарты 17, 20, 23), STL, Boost
• Linux-среда, systemd, D-Bus, Yocto, bash, Python
• Работа с ядром прошивки OpenBMC, взаимодействие с UEFI/BIOS
• Разработка и поддержка сложных интерфейсов встроенных систем
💼 Условия работы:
• Гибкий формат: удалённо или в офисах в Москве, Санкт-Петербурге, Екатеринбурге, Нижнем Новгороде и Минске
• Работа с масштабными проектами в уникальной команде инженеров
• Возможность горизонтального и вертикального карьерного роста
Please open Telegram to view this post
VIEW IN TELEGRAM
std::thread
Чтобы создать поток, можно использовать конструктор класса
В примере на картинке функция
#для_начинающих
std::thread
— это класс из стандартной библиотеки С++, который представляет собой поток выполнения. Потоки выполнения — это независимые единицы, которые могут выполняться параллельно друг с другом.Чтобы создать поток, можно использовать конструктор класса
std::thread
. Конструктор принимает в качестве аргумента указатель на функцию или объект, который будет выполняться в потоке.В примере на картинке функция
foo()
будет выполняться в отдельном потоке. После создания потока мы вызываем его метод join()
, чтобы дождаться его завершения.#для_начинающих
#вопросы_с_собеседований
Объясните концепцию и применение шаблонов политик в C++ и как они способствуют принципам проектирования, основанным на композиции вместо наследования
Шаблоны политик в C++ представляют собой технику проектирования, при которой поведение класса параметризуется через шаблоны. Это позволяет программистам выбирать или изменять аспекты поведения класса на этапе компиляции, вставляя разные "политики" — это могут быть классы или функции, определяющие определённые аспекты поведения. Этот подход способствует гибкости и повторному использованию кода, позволяя композицию поведения вместо жёсткого наследования. Он также помогает уменьшить связность кода и увеличивает его модульность, поскольку изменения в одной политике не влияют на другие.
Объясните концепцию и применение шаблонов политик в C++ и как они способствуют принципам проектирования, основанным на композиции вместо наследования
Шаблоны политик в C++ представляют собой технику проектирования, при которой поведение класса параметризуется через шаблоны. Это позволяет программистам выбирать или изменять аспекты поведения класса на этапе компиляции, вставляя разные "политики" — это могут быть классы или функции, определяющие определённые аспекты поведения. Этот подход способствует гибкости и повторному использованию кода, позволяя композицию поведения вместо жёсткого наследования. Он также помогает уменьшить связность кода и увеличивает его модульность, поскольку изменения в одной политике не влияют на другие.