Современный C++ безопасное использование
Авторы: Джон Лакос, Витторио Ромео,
Ростислав Хлебников
Дата выхода: 2023
#cpp #ru #2O23
Скачать книгу
Авторы: Джон Лакос, Витторио Ромео,
Ростислав Хлебников
Дата выхода: 2023
#cpp #ru #2O23
Скачать книгу
👍2
Неименованные параметры функций
С++ позволяет не указывать имена параметров функций, если они не используются в коде.
Это можно делать и в объявлении функции, и в ее определении.
Важный момент, что отсутствие имени параметра не говорит о том, что параметра нет и его не нужно передавать. Для вызова такой функции вы должны передать в нее аргумент соответствующего типа. Даже если он ничего не делает полезного.
Но вот вопрос возникает тогда. Если параметр ничего не делает, нахрена он тогда вообще нужен?
На самом деле много кейсов, где неименованный параметр может пригодится.
💥 Допустим, у вас есть функция, которая используется в очень многих местах кода, может даже через какие-нибудь указатели на функцию. И в один момент времени часть функционала стала ненужной и один или несколько параметров стали ненужны. Править все вызовы этой функции было бы болью, особенно если туда вовлечены function поинтеры. Вместо этого вы можете сделать эти параметры безымянными, чтобы явно в коде показать, что этот параметр не используется. Его и нельзя даже будет использовать.
💥 Заглушки. Зачастую для тестирования функциональности применяют сущности-болванки, которые внешне ведут себя, как нормальные ребята, но на самом деле они лодыри и ничего путного не делают. Это нужно для мокания соседних модулей, чтобы протестировать только функциональность выбранного набора модулей. Такие заглушки должны выглядеть подобающе, то есть полностью повторять апи замоканой сущности, но могут не делать никакой полезной работы. Поэтому можно в этом апи сделать безымянные параметры, чтобы еще раз подчеркнуть, что они не используются.
💥 Иногда существующие сущности в коде требуют коллбэки определенного вида. И вам в своем коллбэке возможно не нужно использовать весь набор параметров. Но для соблюдения апи вы должны их указать в сигнатуре своего обратного вызова. В этом случае можно сделать эти параметры безымянными.
💥 Иногда в иерархии полиморфных классов в конкретном наследнике вам не нужны все параметры виртуальной функции. Но для поддержания корректности переопределения виртуального интерфейса вы должны включить все параметры в сигнатуру метода. Опять же, неиспользуемые параметры можно пометить безымянными.
💥 Знаменитая перегрузка постфиксного оператора инкремента/декремента. Есть 2 вида этих операторов: префикстный и постфиксный. Проблема в том, что это все еще вызов функции operator++. Как различить реализации этих функций? Правильно, нужна перегрузка. Вот здесь и приходит на помощь безымянный параметр: в коде он не нужен, но влияет на выбор конкретной перегрузки. Выглядит это так:
В целом, эта фича нужна либо для соблюдения существующего апи, либо для того, чтобы при вызове функции гарантировано вызвалась правильная перегрузка.
Stay useful. Stay cool.
📣 Уютное сообщество С++ разработчиков #cppcore #design
С++ позволяет не указывать имена параметров функций, если они не используются в коде.
void foo(int /no name here/);
void foo(int /no name here/)
{
std::cout << "foo" << std::endl;
}
foo(5);
Это можно делать и в объявлении функции, и в ее определении.
Важный момент, что отсутствие имени параметра не говорит о том, что параметра нет и его не нужно передавать. Для вызова такой функции вы должны передать в нее аргумент соответствующего типа. Даже если он ничего не делает полезного.
Но вот вопрос возникает тогда. Если параметр ничего не делает, нахрена он тогда вообще нужен?
На самом деле много кейсов, где неименованный параметр может пригодится.
💥 Допустим, у вас есть функция, которая используется в очень многих местах кода, может даже через какие-нибудь указатели на функцию. И в один момент времени часть функционала стала ненужной и один или несколько параметров стали ненужны. Править все вызовы этой функции было бы болью, особенно если туда вовлечены function поинтеры. Вместо этого вы можете сделать эти параметры безымянными, чтобы явно в коде показать, что этот параметр не используется. Его и нельзя даже будет использовать.
💥 Заглушки. Зачастую для тестирования функциональности применяют сущности-болванки, которые внешне ведут себя, как нормальные ребята, но на самом деле они лодыри и ничего путного не делают. Это нужно для мокания соседних модулей, чтобы протестировать только функциональность выбранного набора модулей. Такие заглушки должны выглядеть подобающе, то есть полностью повторять апи замоканой сущности, но могут не делать никакой полезной работы. Поэтому можно в этом апи сделать безымянные параметры, чтобы еще раз подчеркнуть, что они не используются.
💥 Иногда существующие сущности в коде требуют коллбэки определенного вида. И вам в своем коллбэке возможно не нужно использовать весь набор параметров. Но для соблюдения апи вы должны их указать в сигнатуре своего обратного вызова. В этом случае можно сделать эти параметры безымянными.
💥 Иногда в иерархии полиморфных классов в конкретном наследнике вам не нужны все параметры виртуальной функции. Но для поддержания корректности переопределения виртуального интерфейса вы должны включить все параметры в сигнатуру метода. Опять же, неиспользуемые параметры можно пометить безымянными.
💥 Знаменитая перегрузка постфиксного оператора инкремента/декремента. Есть 2 вида этих операторов: префикстный и постфиксный. Проблема в том, что это все еще вызов функции operator++. Как различить реализации этих функций? Правильно, нужна перегрузка. Вот здесь и приходит на помощь безымянный параметр: в коде он не нужен, но влияет на выбор конкретной перегрузки. Выглядит это так:
struct Digit
{
Digit(int digit=0) : m_digit{digit} {}
Digit& operator++(); // prefix has no parameter
Digit operator++(int); // postfix has an int parameter
private:
int m_digit{};
};
В целом, эта фича нужна либо для соблюдения существующего апи, либо для того, чтобы при вызове функции гарантировано вызвалась правильная перегрузка.
Stay useful. Stay cool.
Please open Telegram to view this post
VIEW IN TELEGRAM
•
push_back
— добавляет копию переданного объекта в конец вектора, вызывая конструктор копирования.•
emplace_back
— создает объект прямо в конце вектора на месте, избегая копирования и вызывая конструктор с переданными аргументами.🔥 — если узнал новое
🤝 — если уже пользовался
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Удаляем элемент из ассоциативного контейнера по значению
Понимаю, что искать элементы ассоциативного контейнера предполагается чисто по ключу. Иначе зачем бы мы использовали этот тип контейнера?
Но вот бывают иногда случаи, когда под вашу задачу очень хорошо подходит мапа, но, чтобы держать ее в консистентном состоянии, вам нужно иногда удалять элементы по значению.
Не все хотят тянуть себе в проект какой-нибудь буст с его bimap или прочие сторонние решения. Хочется чего-нибудь стандартного. Понятное дело, что это не будет эффективно и удалять мы будем за линейное время. Но все же...
У ассоциативных контейнеров есть только один метод на удаление элементов - erase. Он принимает либо итератор, либо ключ. И нет такой перегрузки, которая бы как-то на значение смотрела. То есть нужно делать так:
Две строчки на идейно очень простое и понятное действие. Ох, если бы был метод erase_if...
И вы знаете, в С++20 появились перегрузки свободной функции std::erase_if для каждого стандартного контейнера. Теперь можно написать просто вот так:
И результат вывода будет таким же.
У кого есть только древние плюсы - не переживайте. Для вас эти перегрузки реализовали в экспериментальной библиотеке. Просто сделайте так:
И все заработает.
Do things easier. Stay cool.
#STL #cpp20
Понимаю, что искать элементы ассоциативного контейнера предполагается чисто по ключу. Иначе зачем бы мы использовали этот тип контейнера?
Но вот бывают иногда случаи, когда под вашу задачу очень хорошо подходит мапа, но, чтобы держать ее в консистентном состоянии, вам нужно иногда удалять элементы по значению.
Не все хотят тянуть себе в проект какой-нибудь буст с его bimap или прочие сторонние решения. Хочется чего-нибудь стандартного. Понятное дело, что это не будет эффективно и удалять мы будем за линейное время. Но все же...
У ассоциативных контейнеров есть только один метод на удаление элементов - erase. Он принимает либо итератор, либо ключ. И нет такой перегрузки, которая бы как-то на значение смотрела. То есть нужно делать так:
std::map<int, int> map{{1, 6}, {2, 7}, {3, 8}, {4, 9}, {5, 10}};
// вот так
auto it = std::find_if(map.begin(), map.end(), [](const auto& elem) {return elem.second == 10;});
map.erase(it);
//
std::for_each(map.begin(), map.end(), [](const auto& item){
std::cout << item.first << " " << item.second << std::endl;});
// OUTPUT
// 1 6
// 2 7
// 3 8
// 4 9
Две строчки на идейно очень простое и понятное действие. Ох, если бы был метод erase_if...
И вы знаете, в С++20 появились перегрузки свободной функции std::erase_if для каждого стандартного контейнера. Теперь можно написать просто вот так:
std::erase_if(map, [](const auto& elem) {return elem.second == 10;});
И результат вывода будет таким же.
У кого есть только древние плюсы - не переживайте. Для вас эти перегрузки реализовали в экспериментальной библиотеке. Просто сделайте так:
#include <experimental/map>
std::experimental::erase_if(map, [](const auto& elem) {return elem.second == 10;});
И все заработает.
Do things easier. Stay cool.
#STL #cpp20
Важный аспект программирования на C++, так как язык предоставляет разработчику возможность контролировать выделение и освобождение памяти.
Основные моменты:
• Выделение памяти — new для выделения памяти в динамической памяти.
• Освобождение памяти — delete для освобождения выделенной памяти.
• Массивы — Для массивов используйте new[] и delete[].
🔥 — если узнал новое
🤝 — если уже пользовался
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
C/C++ Ready | Программирование
Авторский канал по разработке на C и C++.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
🤯1🤝1
This media is not supported in your browser
VIEW IN TELEGRAM
codechef — на платформе доступно множество языков программирования, в том числе и C++. Задачи можно решать прямо в редакторе кода, а встроенный AI-ассистент поможет найти и исправить ошибку в коде.
📌 Ссылочка: https://www.codechef.com/learn
📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
Modern C++ for Absolute Beginners
Автор: Slobodan Dmitrović
Год издания: 2023
#cpp #en #2O23
Скачать книгу
Автор: Slobodan Dmitrović
Год издания: 2023
#cpp #en #2O23
Скачать книгу
👍2
Обратный код
Обратный код или ones' complement - уже более совершенное представление целых чисел в двоичном виде. Этот код позволяет очень легко выполнять операции сложения/вычитания над числами, используя только лишь операцию сложения.
Вообще говоря, в арифметике операцию вычитания можно переопределить через операцию сложения. Вместо вычитания одного числа из другого, вы инвертируете вычитаемое и складываете с уменьшаемым. Типа того:
Обратный код очень удобно использовать именно в контексте такого свойства, потому что в нем очень просто инвертируются числа.
Как и во всех системах, поддерживающих представление отрицательных чисел, в нем есть зарезервированный знаковый бит, а затем идет "модуль" числа. Например, число 5 в двоичном виде представляется, как 101. Восьмибиное знаковое число 5 в обратном коде представляется, как 00000101. Старший бит 0 значит, что число положительное, дальше идут незначащие нули и в конце наше число.
Инвертированное же число получается просто обращением всех битов в обратные. 0 в 1 и 1 в 0.
То есть число -5 представляется, как 11111010.
И если мы сложим 2 обратных числа, то получим естественно 0:
Причем складываются два числа без учета "особенности" старшего бита. Сложение происходит просто как сложение двух двоичных чисел. Если сумма не умещается в заданное количество бит, то новый старший разряд просто откидывается.
Давайте попробуем что-нибудь посчитать:
Получили ожидаемое положительное(знаковый бит 0) число 19.
Можем уйти в минуса:
Вот так все просто.
Но и у этого кода есть недостатки. Главный из них вы уже могли заметить в посте. Ноль представляется, как 11111111. Точнее, у нуля 2 значения - все нули и все единички. То есть появляется +0 и -0.
С точки зрения вычислений это особо никак не влияет на результат, но добавляет головной боли при разработке, так как надо тестировать софт и для отрицательного нуля.
Недостаток довольно надоедливый. Поэтому, и хоть динозавристые компьютеры использовали этот код, все современный машины используют дополнительный код. О нем в следующем посте.
Remove inconvenience from your life. Stay cool.
#base
Обратный код или ones' complement - уже более совершенное представление целых чисел в двоичном виде. Этот код позволяет очень легко выполнять операции сложения/вычитания над числами, используя только лишь операцию сложения.
Вообще говоря, в арифметике операцию вычитания можно переопределить через операцию сложения. Вместо вычитания одного числа из другого, вы инвертируете вычитаемое и складываете с уменьшаемым. Типа того:
a - b = a + (-b)
Обратный код очень удобно использовать именно в контексте такого свойства, потому что в нем очень просто инвертируются числа.
Как и во всех системах, поддерживающих представление отрицательных чисел, в нем есть зарезервированный знаковый бит, а затем идет "модуль" числа. Например, число 5 в двоичном виде представляется, как 101. Восьмибиное знаковое число 5 в обратном коде представляется, как 00000101. Старший бит 0 значит, что число положительное, дальше идут незначащие нули и в конце наше число.
Инвертированное же число получается просто обращением всех битов в обратные. 0 в 1 и 1 в 0.
То есть число -5 представляется, как 11111010.
И если мы сложим 2 обратных числа, то получим естественно 0:
00000101 + 11111010 = 11111111 = 0
Причем складываются два числа без учета "особенности" старшего бита. Сложение происходит просто как сложение двух двоичных чисел. Если сумма не умещается в заданное количество бит, то новый старший разряд просто откидывается.
Давайте попробуем что-нибудь посчитать:
31 - 12 = 31 + (-12) = 00100000 + (-00001100) = 00100000 + 11110011 = 1'00010011(старший разряд откидываем, у нас всего 8 бит) = 00010011 = 19
Получили ожидаемое положительное(знаковый бит 0) число 19.
Можем уйти в минуса:
25 - 29 = 25 + (-29) = 00011001 + (-00011101) = 00011001 + 11100010 = 11111011 = -00000100 = -4
Вот так все просто.
Но и у этого кода есть недостатки. Главный из них вы уже могли заметить в посте. Ноль представляется, как 11111111. Точнее, у нуля 2 значения - все нули и все единички. То есть появляется +0 и -0.
С точки зрения вычислений это особо никак не влияет на результат, но добавляет головной боли при разработке, так как надо тестировать софт и для отрицательного нуля.
Недостаток довольно надоедливый. Поэтому, и хоть динозавристые компьютеры использовали этот код, все современный машины используют дополнительный код. О нем в следующем посте.
Remove inconvenience from your life. Stay cool.
#base
👍2
<algorithm> — предоставляет набор стандартных алгоритмов для работы с контейнерами, такими как массивы, векторы и другие последовательности, включает множество полезных инструментов для обработки данных.
Основные алгоритмы:
• std::sort — сортирует элементы диапазона.
• std::find — ищет элемент в контейнере.
• std::reverse — переворачивает элементы диапазона.
🔥 — если узнал новое
🤝 — если уже пользовался
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
C/C++ Ready | Программирование
Авторский канал по разработке на C и C++.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
🔥2
Присвоение лямбды
#новичкам
Изучение лямбда выражений - не самая простая задача для начинающего плюсовика. Сложные термины, какие-то замыкания, списки захвата и прочее. В общем, непросто. И с виду можно подумать, что 2 одинаковые лямбды можно присваивать друг другу с легкостью. То есть может показаться, что такой код валидный:
Однако он генерирует примерно следующую ошибку:
Не нашел нужного оператора присваивания.
Да и вообще, это ж все лямбды, почему я не могу их присваивать друг другу?
Дело в том, что каждое отдельное лямбда-выражение генерирует свой тип, который называется замыканием. Только компилятор знает этот тип, вы его наружу никак не можете получить. Стандарт говорит:
Это легко проверить. Такой код выведет 0:
Типы действительно разные.
В целом, поэтому вместе с лямбдами всегда нужно использовать auto. Потому что ничего другого вы вместо типа физически не сможете написать. Но компилятор знает тип замыкания и сможет вывести правильный тип для переменной.
Ну и естественно, для двух рандомных классов неопределены операторы присваивания своих объектов друг другу. Поэтому код из начала и фейлится.
Differentiate thing apart. Stay cool.
#cpp11
#новичкам
Изучение лямбда выражений - не самая простая задача для начинающего плюсовика. Сложные термины, какие-то замыкания, списки захвата и прочее. В общем, непросто. И с виду можно подумать, что 2 одинаковые лямбды можно присваивать друг другу с легкостью. То есть может показаться, что такой код валидный:
int main() {
auto test = [](){};
test = [](){};
return 0;
}
Однако он генерирует примерно следующую ошибку:
In function ‘int main()’:
error: no match for ‘operator=’ in ‘test = <lambda closure object>main()::<lambda()>{}’
note: candidate is:
note: main()::<lambda()>& main()::<lambda()>::operator=(const main()::<lambda()>&) <deleted>
no known conversion for argument 1 from ‘main()::<lambda()>’ to ‘const main()::<lambda()>&’
Не нашел нужного оператора присваивания.
Да и вообще, это ж все лямбды, почему я не могу их присваивать друг другу?
Дело в том, что каждое отдельное лямбда-выражение генерирует свой тип, который называется замыканием. Только компилятор знает этот тип, вы его наружу никак не можете получить. Стандарт говорит:
The type of the lambda-expression [...] is a unique, unnamed non-union class type — called the closure type.
Это легко проверить. Такой код выведет 0:
auto test = [](){};
auto test2 = [](){};
std::cout << std::is_same_v<decltype( test ), decltype( test2 )> << std::endl;
Типы действительно разные.
В целом, поэтому вместе с лямбдами всегда нужно использовать auto. Потому что ничего другого вы вместо типа физически не сможете написать. Но компилятор знает тип замыкания и сможет вывести правильный тип для переменной.
Ну и естественно, для двух рандомных классов неопределены операторы присваивания своих объектов друг другу. Поэтому код из начала и фейлится.
Differentiate thing apart. Stay cool.
#cpp11
👍2
std::filesystem — предоставляет функционал для работы с файлами и директориями, позволяет выполнять итерацию по содержимому директорий и получать информацию о файлах, например, их размер.
Основные возможности и общий функционал читай на картинках выше👆
🔥 — если узнал новое
🤝 — если уже пользовался
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
C/C++ Ready | Программирование
Авторский канал по разработке на C и C++.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
This media is not supported in your browser
VIEW IN TELEGRAM
Основы С++ — хендбук от Яндекса по C++, в котором вы познакомитесь с основами языка, а так же более сложными темами и познакомитесь с основными библиотеками.
⛓ Ссылочка: https://education.yandex.ru/handbook/cpp
📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
std::map — это контейнер, который хранит данные в виде пар ключ-значение, где ключи уникальны и автоматически сортируются.
Он автоматически сортирует элементы по ключам и обеспечивает быстрый поиск, вставку и удаление данных на основе ключей.
• insert() — вставляет новую пару ключ-значение
• find() — находит элемент по ключу
• erase() — удаляет элемент по ключу.
• size() — возвращает количество элементов в std::map
🔥 — если узнал новое
🤝 — если уже пользовался
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
C/C++ Ready | Программирование
Авторский канал по разработке на C и C++.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Автор: @energy_it
Реклама на бирже: https://telega.in/c/cpp_ready
🤝2
Programming: Principles and Practice Using C++
Автор: Bjarne Stroustrup
Год издания: 2023
#en #cpp #2O23
Скачать книгу
Автор: Bjarne Stroustrup
Год издания: 2023
#en #cpp #2O23
Скачать книгу
👍1
Подробно рассказываем о высокопроизводительных решениях с фреймворком userver на новом бесплатном вебинаре!
Он предназначен для создания надежных и молниеносных микросервисов и веб-серверов. Освойте передовой C++ фреймворк всего за 90 минут!
✅ Вы узнаете:
- Уникальные архитектурные особенности и преимущества userver, которые сделают вашу работу легче и эффективнее.
- Как быстро настроить окружение и запустить свой первый проект, не тратя лишнего времени.
- Советы высококлассных профессионалов по работе с асинхронностью, которые помогут вам стать мастером своего дела и очень много другой полезной сочной информации!
💡 Будет особенно интересно:
- C++ разработчикам, стремящимся освоить мощный инструмент для создания микросервисов.
- Backend-инженерам и Team Lead'ам, ищущим высокопроизводительные решения для своих задач.
- Специалистам, работающим над масштабируемыми системами.
❌ ❌ Получите практический и ценный опыт работы с userver, который можно сразу применить в своих проектах - регистрируйтесь по ссылке
P.S. Все зарегистрированные участники получат приличную скидку на обновленный топовый курс «C++ Developer. Professional»
Он предназначен для создания надежных и молниеносных микросервисов и веб-серверов. Освойте передовой C++ фреймворк всего за 90 минут!
- Уникальные архитектурные особенности и преимущества userver, которые сделают вашу работу легче и эффективнее.
- Как быстро настроить окружение и запустить свой первый проект, не тратя лишнего времени.
- Советы высококлассных профессионалов по работе с асинхронностью, которые помогут вам стать мастером своего дела и очень много другой полезной сочной информации!
- C++ разработчикам, стремящимся освоить мощный инструмент для создания микросервисов.
- Backend-инженерам и Team Lead'ам, ищущим высокопроизводительные решения для своих задач.
- Специалистам, работающим над масштабируемыми системами.
P.S. Все зарегистрированные участники получат приличную скидку на обновленный топовый курс «C++ Developer. Professional»
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Статья дня. Параллельный метод сортировки массива std::thread
Принцип «разделяй и властвуй» является одной из фундаментальных стратегий в разработке параллельных алгоритмов. Он заключается в разбиении задачи на более мелкие подзадачи, решение которых происходит независимо, а затем объединении результатов этих подзадач для получения окончательного результата.
Читать статью
#читать
Принцип «разделяй и властвуй» является одной из фундаментальных стратегий в разработке параллельных алгоритмов. Он заключается в разбиении задачи на более мелкие подзадачи, решение которых происходит независимо, а затем объединении результатов этих подзадач для получения окончательного результата.
Читать статью
#читать
Подробно рассказываем о высокопроизводительных решениях с фреймворком userver на новом бесплатном вебинаре!
Он предназначен для создания надежных и молниеносных микросервисов и веб-серверов. Освойте передовой C++ фреймворк всего за 90 минут!
✅ Вы узнаете:
- Уникальные архитектурные особенности и преимущества userver, которые сделают вашу работу легче и эффективнее.
- Как быстро настроить окружение и запустить свой первый проект, не тратя лишнего времени.
- Советы высококлассных профессионалов по работе с асинхронностью, которые помогут вам стать мастером своего дела и очень много другой полезной сочной информации!
💡 Будет особенно интересно:
- C++ разработчикам, стремящимся освоить мощный инструмент для создания микросервисов.
- Backend-инженерам и Team Lead'ам, ищущим высокопроизводительные решения для своих задач.
- Специалистам, работающим над масштабируемыми системами.
❌ ❌ Получите практический и ценный опыт работы с userver, который можно сразу применить в своих проектах - регистрируйтесь по ссылке
P.S. Все зарегистрированные участники получат приличную скидку на обновленный топовый курс «C++ Developer. Professional»
Он предназначен для создания надежных и молниеносных микросервисов и веб-серверов. Освойте передовой C++ фреймворк всего за 90 минут!
- Уникальные архитектурные особенности и преимущества userver, которые сделают вашу работу легче и эффективнее.
- Как быстро настроить окружение и запустить свой первый проект, не тратя лишнего времени.
- Советы высококлассных профессионалов по работе с асинхронностью, которые помогут вам стать мастером своего дела и очень много другой полезной сочной информации!
- C++ разработчикам, стремящимся освоить мощный инструмент для создания микросервисов.
- Backend-инженерам и Team Lead'ам, ищущим высокопроизводительные решения для своих задач.
- Специалистам, работающим над масштабируемыми системами.
P.S. Все зарегистрированные участники получат приличную скидку на обновленный топовый курс «C++ Developer. Professional»
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM