en
Feedback

Don't get caught by a cheater! Telemetrio finds and tags such channels 👉 If you want to see the tag, subscribe

C++ geek

C++ geek

Open in Telegram

Учим C/C++ на примерах

Show more
3 504
Subscribers
No data24 hours
-27 days
-2630 days
Posts Archive
📌 Оптимизация кода в C++: Используем std::move правильно! Привет, друзья! Сегодня я расскажу об одной из самых частых ошибок, связанных с std::move. Многие знают, что std::move не перемещает объект, а лишь превращает его в rvalue. Но как его использовать правильно? Давайте разбираться! ❌ Ошибка: Бессмысленный std::move

std::string getString() {
    std::string str = "Hello, world!";
    return std::move(str); // ❌ Неэффективно
}
Что здесь не так? Возвращаемый std::string и так является временным объектом (NRVO — оптимизация возврата), и std::move мешает этой оптимизации! В результате компилятор не сможет выполнить перемещение, а вызовет копирование. ✅ Правильный вариант:

std::string getString() {
    return "Hello, world!"; // ✅ NRVO оптимизация
}
🏆 Где std::move полезен? Используйте std::move, когда точно знаете, что объект больше не нужен и его можно переместить:

void processString(std::string str) { /* ... */ }

int main() {
    std::string s = "Example";
    processString(std::move(s)); // 🔥 Теперь перемещение!
}
1️⃣ Не используйте std::move при возврате локальных объектов — дайте компилятору сделать свое дело! 2️⃣ Используйте std::move, когда объект больше не нужен — это ускорит работу кода. 3️⃣ После std::move не используйте переменную, кроме как для присвоения нового значения. ➡️ @cpp_geek

🔥 Оптимизация кода на C++: Ранний возврат вместо вложенных условий Привет, друзья! Сегодня хочу поговорить об одной важной технике, которая делает код чище и читабельнее - ранний возврат (early return). Часто встречаю код, который уходит в глубину вложенных if, превращаясь в настоящий лабиринт. Давайте разберем, как этого избежать. ❌ Плохой пример: Вложенные условия

void process(int value) {
    if (value > 0) {
        if (value % 2 == 0) {
            if (value < 100) {
                std::cout << "Обрабатываем " << value << std::endl;
            } else {
                std::cout << "Слишком большое число" << std::endl;
            }
        } else {
            std::cout << "Нечетное число" << std::endl;
        }
    } else {
        std::cout << "Отрицательное число" << std::endl;
    }
}
Здесь код уходит вглубь из-за множества вложенных if, что делает его сложным для чтения. ✅ Хороший пример: Ранний возврат

void process(int value) {
    if (value <= 0) {
        std::cout << "Отрицательное число" << std::endl;
        return;
    }
    if (value % 2 != 0) {
        std::cout << "Нечетное число" << std::endl;
        return;
    }
    if (value >= 100) {
        std::cout << "Слишком большое число" << std::endl;
        return;
    }

    std::cout << "Обрабатываем " << value << std::endl;
}
Теперь код сразу проверяет граничные условия и делает ранний возврат (return), если условия не выполнены. В итоге у нас получился плоский код, который проще читать и сопровождать. 🎯 Вывод: - Избегайте вложенных if, если можно этого не делать. - Используйте ранний возврат, чтобы код был линейным и понятным. - Чем меньше уровней вложенности - тем легче отладка и сопровождение. ➡️ @cpp_geek

🔥 Оптимизация кода на C++: Ранний возврат вместо вложенных условий Привет, друзья! Сегодня хочу поговорить об одной важной технике, которая делает код чище и читабельнее — ранний возврат (early return). Часто встречаю код, который уходит в глубину вложенных if, превращаясь в настоящий лабиринт. Давайте разберем, как этого избежать. ❌ Плохой пример: Вложенные условия

void process(int value) {
    if (value > 0) {
        if (value % 2 == 0) {
            if (value < 100) {
                std::cout << "Обрабатываем " << value << std::endl;
            } else {
                std::cout << "Слишком большое число" << std::endl;
            }
        } else {
            std::cout << "Нечетное число" << std::endl;
        }
    } else {
        std::cout << "Отрицательное число" << std::endl;
    }
}
Здесь код уходит вглубь из-за множества вложенных if, что делает его сложным для чтения. ✅ Хороший пример: Ранний возврат

void process(int value) {
    if (value <= 0) {
        std::cout << "Отрицательное число" << std::endl;
        return;
    }
    if (value % 2 != 0) {
        std::cout << "Нечетное число" << std::endl;
        return;
    }
    if (value >= 100) {
        std::cout << "Слишком большое число" << std::endl;
        return;
    }

    std::cout << "Обрабатываем " << value << std::endl;
}
Теперь код сразу проверяет граничные условия и делает ранний возврат (return), если условия не выполнены. В итоге у нас получился плоский код, который проще читать и сопровождать. 🎯 Вывод: - Избегайте вложенных if, если можно этого не делать. - Используйте ранний возврат, чтобы код был линейным и понятным. - Чем меньше уровней вложенности — тем легче отладка и сопровождение. ➡️ @cpp_geek

📌 Оптимизация кода: std::string_view вместо std::string Привет, друзья! Сегодня хочу рассказать про std::string_view — полезный инструмент, который может значительно ускорить работу с строками в C++. Многие из вас, вероятно, используют std::string, но не всегда это лучший выбор. ❓ Что такое std::string_view? Это некопируемая, легковесная оболочка над строковыми данными. Она просто хранит указатель на начало строки и её длину, не создавая копии. Использование std::string_view вместо std::string позволяет избежать ненужных аллокаций памяти и ускорить код. 🔥 Пример использования:

#include <iostream>
#include <string_view>

void print(std::string_view str) {  // Без лишнего копирования
    std::cout << str << '\n';
}

int main() {
    std::string s = "Hello, world!";
    print(s);         // Можно передавать std::string
    print("Hi there"); // Можно передавать строковый литерал
}
🛠 Когда использовать? ✅ При передаче строк в функции, если их не нужно модифицировать. ✅ Для работы с подстроками (в отличие от std::string::substr, который делает копию). ✅ Для обработки строк без создания динамических объектов. ⚠️ Важно помнить: - std::string_view не владеет данными, поэтому нельзя использовать его для длительного хранения указателей на временные строки. - Нужно быть осторожным с объектами, чей срок жизни может закончиться, пока std::string_view ещё используется. 🚀 Итог: Использование std::string_view вместо const std::string& может ускорить работу с текстовыми данными и снизить нагрузку на аллокатор. Если не нужно изменять строку — это отличный выбор! А вы уже используете std::string_view в своих проектах? Делитесь в комментариях! ⬇️ ➡️ @cpp_geek

📌 Уменьшаем размер исполняемого файла в C++ Всем добрый вечер! Хочу поделиться парой трюков, которые помогут уменьшить размер исполняемого файла вашей программы на C++. Это полезно, если вы пишете под встраиваемые системы, создаёте утилиты или просто хотите более компактный бинарник. 🔹 1. Отключаем отладочную информацию Компиляторы по умолчанию добавляют отладочные символы в бинарник. Их можно убрать флагами:

g++ -o my_program my_program.cpp -O2 -s
Флаг -s удаляет все отладочные символы. 🔹 2. Оптимизируем код Используйте -O2 или -Os, чтобы компилятор оптимизировал код для уменьшения размера:

g++ -o my_program my_program.cpp -Os
Флаг -Os специально оптимизирует код для минимального размера. 🔹 3. Статическая или динамическая линковка? Если в системе уже есть нужные библиотеки, используйте динамическую линковку (-shared для .so в Linux, /MD в MSVC). Но иногда статическая линковка (флаг -static) позволяет избавиться от лишних зависимостей. 🔹 4. Убираем ненужные зависимости Можно использовать strip, чтобы дополнительно очистить бинарник:

strip my_program
А ещё, если пишете на C++, то не забывайте про -ffunction-sections -fdata-sections и --gc-sections, чтобы убрать неиспользуемый код. 🔹 5. Убираем RTTI и исключения Если не используете dynamic_cast и исключения, отключите их:

g++ -o my_program my_program.cpp -Os -fno-rtti -fno-exceptions
Это существенно уменьшит размер! ➡️ @cpp_geek

📌 Оптимизация использования std::unordered_map в C++ Сегодня я расскажу вам, как оптимизировать работу std::unordered_map и избежать неожиданных тормозов. std::unordered_map — мощная хеш-таблица в C++, но при неправильном использовании она может замедлить ваш код. Давайте разберем основные моменты, которые помогут избежать проблем. 🔥 1. Выбирайте правильный хеш-функтор По умолчанию std::unordered_map использует std::hash<Key>, но если ключ — это пользовательский тип данных (например, struct`), то стандартного `std::hash не существует, и придется писать свой. Пример кастомного хеша для структуры:

struct MyKey {
    int x, y;

    bool operator==(const MyKey& other) const {
        return x == other.x && y == other.y;
    }
};

struct MyHash {
    size_t operator()(const MyKey& key) const {
        return std::hash<int>{}(key.x) ^ (std::hash<int>{}(key.y) << 1);
    }
};

std::unordered_map<MyKey, std::string, MyHash> my_map;
Используем ^ (XOR) и << (битовый сдвиг), чтобы уменьшить коллизии. ⚡ 2. Контролируйте размер bucket'ов Если std::unordered_map сильно увеличивается, он перехеширует (rehash), что может быть дорогой операцией. Чтобы избежать лишних перераспределений:

my_map.reserve(10000); // Подготавливаем место под 10,000 элементов
Это ускорит вставку, так как уменьшит количество перераспределений памяти. 🚀 3. Избегайте ненужного копирования ключей Если ключ — это сложный объект, избегайте его копирования:

std::unordered_map<std::string, int> data;
std::string key = "long_key_string";

int value = data[key]; // ❌ НЕ ЭФФЕКТИВНО: создаст пустую запись, если ключа нет
int value = data.at(key); // ✅ БЫСТРЕЕ: выбросит исключение, если ключа нет
Еще лучше использовать find():

auto it = data.find(key);
if (it != data.end()) {
    int value = it->second;
}
🏆 Вывод ✅ Используйте кастомные хеш-функции, если ключи нестандартные ✅ Резервируйте память заранее (reserve) ✅ Уменьшайте копирование ключей, используя find() и at() А вы используете std::unordered_map в своих проектах? Может, у вас есть свои фишки? Пишите в комментариях! 👇🚀 ➡️ @cpp_geek

📌 Оптимизация кода: стоит ли всегда инлайнить функции? Привет, сегодня поговорим о inline функциях в C++. Часто вижу, как новички (да и не только) злоупотребляют этим ключевым словом. Давайте разберемся, стоит ли всегда использовать inline для оптимизации кода. 🔎 Что делает inline? Когда вы помечаете функцию как inline, компилятор может (но не обязан) заменить вызовы этой функции её телом, чтобы избежать накладных расходов на вызов. 🔥 Когда inline полезен? ✅ Очень короткие функции (1-2 строчки). Например:

inline int square(int x) { return x * x; }
✅ Геттеры и сеттеры в классах, если они простые. ✅ Функции-хелперы в заголовочных файлах (например, в `namespace`-ах). ⚠️ Когда inline во вред? ❌ Большие функции. Раздувает бинарник, увеличивает время компиляции. ❌ Часто изменяемый код. Так как `inline`-функции вставляются в код, изменение их логики требует перекомпиляции всех файлов, где они были вызваны. ❌ Чрезмерное использование. Вставка слишком многих `inline`-функций может снизить эффективность процессорного кеша, что приведет к ухудшению производительности. 🎯 Альтернатива: constexpr! В C++11 появился constexpr, который не только инлайнит, но и выполняет вычисления на этапе компиляции:

constexpr int cube(int x) { return x * x * x; }
Если можете сделать функцию constexpr — делайте, это лучше, чем просто inline! 🤔 Итог inline — мощный инструмент, но применять его стоит с умом. Лучше доверять компилятору и включить оптимизацию -O2 или -O3, чем разбрасываться inline без разбора. ➡️ @cpp_geek

Запустите рекламу в телеграм-каналах с Яндекс Директом Перфоманс-реклама теперь в телеграм-каналах ⚡ Яндекс Директ знает, как
Запустите рекламу в телеграм-каналах с Яндекс Директом Перфоманс-реклама теперь в телеграм-каналах ⚡ Яндекс Директ знает, как привлечь целевую аудиторию 💰👌 Попробовать #реклама yandex.ru О рекламодателе

Что такое TCP Server Project в C++? 💬 TCP Server Project — это проект, который реализует сервер для обмена данными по протоколу TCP (Transmission Control Protocol). Такой сервер позволяет клиентам подключаться к нему, отправлять запросы и получать ответы через надёжное соединение. На практике TCP-сервер в C++ создаётся с помощью сокетов (например, используя Berkeley sockets на Linux или Winsock на Windows). Процесс обычно включает: • Создание сокета — создаётся дескриптор для коммуникации. • Привязка к порту (bind) — сервер привязывается к определённому порту на хосте. • Прослушивание соединений (listen) — сервер ожидает входящие подключения. • Принятие соединений (accept) — сервер принимает запросы от клиентов. • Обмен данными — сервер и клиент обмениваются сообщениями через соединение. 📌 Пример применения: чаты, игровые серверы, веб-серверы и любые приложения, требующие стабильного соединения с гарантией доставки данных. ➡️ @cpp_geek

🔥 Как правильно сравнивать std::string в C++? Доброй ночи! Давайте разберём важную тему – сравнение std::string в C++. Многие думают, что это просто (== и всё), но есть нюансы! Давайте разберёмся. ✅ Способы сравнения строк 1️⃣ Оператор == Если вам нужно проверить точное совпадение строк:

std::string str1 = "hello";
std::string str2 = "hello";

if (str1 == str2) {
    std::cout << "Строки равны!\n";
}
Этот метод безопасен, читабелен и работает быстро. 2️⃣ Функция compare() Если нужно получить порядок строк в алфавитном сравнении:

std::string str1 = "apple";
std::string str2 = "banana";

if (str1.compare(str2) < 0) {
    std::cout << "apple идет перед banana\n";
}
🔹 compare() возвращает: - 0, если строки равны - < 0, если str1 меньше str2 - > 0, если str1 больше str2 3️⃣ Сравнение без учета регистра В C++ нет встроенного метода, но можно использовать std::transform:

#include <algorithm>
#include <cctype>
#include <string>

bool caseInsensitiveCompare(const std::string& a, const std::string& b) {
    return std::equal(a.begin(), a.end(), b.begin(), b.end(),
                      [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
}

std::string str1 = "Hello";
std::string str2 = "hello";

if (caseInsensitiveCompare(str1, str2)) {
    std::cout << "Строки равны без учета регистра!\n";
}
4️⃣ Сравнение подстрок Если нужно проверить, начинается ли строка с подстроки:

std::string text = "hello world";
std::string prefix = "hello";

if (text.rfind(prefix, 0) == 0) {
    std::cout << "Строка начинается с 'hello'!\n";
}
✅ rfind(prefix, 0) == 0 проверяет, что prefix стоит в начале строки. 🚀 Итоги ✔ Используйте == для простого сравнения ✔ compare() – если важно узнать порядок ✔ Для регистра – std::tolower() ✔ Для подстрок – rfind() Какой метод вы чаще используете? Делитесь в комментариях! ➡️ @cpp_geek

🔥 C++: умные указатели – избавляемся от delete навсегда! Вы все еще вручную освобождаете память? Это уже не актуально! Разбираем умные указатели (std::unique_ptr, std::shared_ptr) и их преимущества. 🔹 std::unique_ptr – для объектов, у которых один владелец. Память освобождается автоматически, когда указатель выходит из области видимости:

#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(42);
    std::cout << *ptr << std::endl; // 42
}
🔹 std::shared_ptr – для объектов, у которых несколько владельцев. Когда последний shared_ptr уничтожается – объект тоже удаляется:

#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(42);
    std::shared_ptr<int> sp2 = sp1; // Теперь два владельца

    std::cout << *sp1 << " " << *sp2 << std::endl; // 42 42
}
❌ Забудьте про new и delete, используйте std::make_unique и std::make_shared. Это избавит вас от утечек памяти. А вы уже полностью отказались от delete? Пишите в комментариях! 👇 ➡️ @cpp_geek

Для чего нужен алгоритм generate? Используется для генерации чисел на основе функции генератора, а затем присваивает эти знач
Для чего нужен алгоритм generate? Используется для генерации чисел на основе функции генератора, а затем присваивает эти значения элементам в контейнере в диапазоне [first, last). ➡️ @cpp_geek

Pipes В C++ пайпы (pipes) представляют собой механизм для односторонней связи между процессами. Они позволяют передавать данн
Pipes В C++ пайпы (pipes) представляют собой механизм для односторонней связи между процессами. Они позволяют передавать данные из одного процесса в другой, где один процесс выступает в роли писателя (write end), а другой процесс выступает в роли читателя (read end) пайпа. Для работы с пайпами вы можете использовать системные вызовы, такие как pipe, fork и функции чтения/записи (read и write), доступные в POSIX-совместимых операционных системах. Обратите внимание, что дескрипторы чтения и записи пайпа должны быть закрыты в соответствующих процессах с помощью close, чтобы гарантировать правильное завершение операций чтения и записи. ➡️ @cpp_geek

🚀 Подборка Telegram каналов для программистов Системное администрирование, DevOps 📌 https://t.me/bash_srv Bash Советы https://t.me/win_sysadmin Системный Администратор Windows https://t.me/sysadmin_girl Девочка Сисадмин https://t.me/srv_admin_linux Админские угодья https://t.me/linux_srv Типичный Сисадмин https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin https://t.me/linux_odmin Linux: Системный администратор https://t.me/devops_star DevOps Star (Звезда Девопса) https://t.me/i_linux Системный администратор https://t.me/linuxchmod Linux https://t.me/sys_adminos Системный Администратор https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало) https://t.me/sysadminof Книги для админов, полезные материалы https://t.me/i_odmin Все для системного администратора https://t.me/i_odmin_book Библиотека Системного Администратора https://t.me/i_odmin_chat Чат системных администраторов https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др. https://t.me/sysadminoff Новости Линукс Linux 1C разработка 📌 https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С https://t.me/DevLab1C 1С:Предприятие 8 https://t.me/razrab_1C 1C Разработчик https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт https://t.me/rabota1C_rus Вакансии для программистов 1С Программирование C++📌 https://t.me/cpp_lib Библиотека C/C++ разработчика https://t.me/cpp_knigi Книги для программистов C/C++ https://t.me/cpp_geek Учим C/C++ на примерах Программирование Python 📌 https://t.me/pythonofff Python академия. https://t.me/BookPython Библиотека Python разработчика https://t.me/python_real Python подборки на русском и английском https://t.me/python_360 Книги по Python Java разработка 📌 https://t.me/BookJava Библиотека Java разработчика https://t.me/java_360 Книги по Java Rus https://t.me/java_geek Учим Java на примерах GitHub Сообщество 📌 https://t.me/Githublib Интересное из GitHub Базы данных (Data Base) 📌 https://t.me/database_info Все про базы данных Мобильная разработка: iOS, Android 📌 https://t.me/developer_mobila Мобильная разработка https://t.me/kotlin_lib Подборки полезного материала по Kotlin https://t.me/androidspb Разработка под Android: Kotlin, Java. Фронтенд разработка 📌 https://t.me/frontend_1 Подборки для frontend разработчиков https://t.me/frontend_sovet Frontend советы, примеры и практика! https://t.me/React_lib Подборки по React js и все что с ним связано Разработка игр 📌 https://t.me/game_devv Все о разработке игр Библиотеки 📌 https://t.me/book_for_dev Книги для программистов Rus https://t.me/programmist_of Книги по программированию https://t.me/proglb Библиотека программиста https://t.me/bfbook Книги для программистов БигДата, машинное обучение 📌 https://t.me/bigdata_1 Big Data, Machine Learning Программирование 📌 https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций https://t.me/rust_lib Полезный контент по программированию на Rust https://t.me/golang_lib Библиотека Go (Golang) разработчика https://t.me/itmozg Программисты, дизайнеры, новости из мира IT https://t.me/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻 https://t.me/nodejs_lib Подборки по Node js и все что с ним связано https://t.me/ruby_lib Библиотека Ruby программиста https://t.me/lifeproger Жизнь программиста. Авторский канал. QA, тестирование 📌 https://t.me/testlab_qa Библиотека тестировщика Шутки программистов 📌 https://t.me/itumor Шутки программистов Защита, взлом, безопасность 📌 https://t.me/thehaking Канал о кибербезопасности https://t.me/xakep_2 Хакер Free Книги, статьи для дизайнеров 📌 https://t.me/ux_web Статьи, книги для дизайнеров Математика 📌 https://t.me/Pomatematike Канал по математике https://t.me/phis_mat Обучающие видео, книги по Физике и Математике https://t.me/matgeoru Математика | Геометрия | Логика Excel лайфхак📌 https://t.me/Excel_lifehack https://t.me/mir_teh Мир технологий (Technology World) Вакансии 📌 https://t.me/sysadmin_rabota Системный Администратор https://t.me/progjob Вакансии в IT

std::initializer_list Присваивайте значения контейнерам непосредственно с помощью списка инициализаторов, как это можно делат
std::initializer_list Присваивайте значения контейнерам непосредственно с помощью списка инициализаторов, как это можно делать с C-массивами. Это справедливо и для вложенных контейнеров. Скажите спасибо С++11. ➡️ @cpp_geek

Городские сервисы Яндекса отправились в Tech Tour — встречайте в Казани и Нижнем Новгороде  15 и 22 ноября приглашаем на митапы о технологиях в Городских сервисах Яндекса — эксперты выступят с докладами, проведут кейслаб и вайбкодинг для backend-, ML- и DS-разработчиков.  📍В Казани расскажут о том, как в Маркете создали AI-ассистента внутри маркетплейса, разработали поиск лекарств в Еде и научились оптимизировать алгоритмы назначения и распределения исполнителей в Лавке.  📍А в Нижнем Новгороде поделятся, как создают сервис Турбо со скидками для пользователей и поддерживают консистентность данных в продукте.  Кроме докладов и практических активностей в каждом городе будут интерактивы, карьерные смолл-токи и нетворкинг.  📌 Казань, 15 ноября 📌 Нижний Новгород, 22 ноября Сохраняйте даты и регистрируйтесь!  Мероприятие бесплатное. Количество мест ограничено — пожалуйста, дождитесь нашего подтверждения.

std::hash Это структура шаблонного класса, определенная в заголовочном файле. Она предоставляет хеш-функцию для хэширования р
std::hash Это структура шаблонного класса, определенная в заголовочном файле. Она предоставляет хеш-функцию для хэширования различных типов данных, включая встроенные и пользовательские. std::hash используется, например, в ассоциативных контейнерах, таких как std::unordered_map и std::unordered_set, для быстрого доступа к элементам по ключу. Для пользовательского типа данных требуется явная специализация структуры std::hash для корректной работы хэширования. ➡️ @cpp_geek

Что случится, если exception выйдет за пределы потока? Если exception выходит за пределы потока, то оно не может быть обработ
Что случится, если exception выйдет за пределы потока? Если exception выходит за пределы потока, то оно не может быть обработано на текущем уровне, т. к. он уже завершен. В таком случае исключение будет зарегистрировано как неперехваченное и может привести к аварийному завершению программы. Чтобы избежать данной ситуации, необходимо обернуть код, где может возникнуть исключение, в try-catch блок на том же уровне, что и поток, с которым он связан. ➡️ @cpp_geek

Dependency Injection Dependency Injection (DI) — это паттерн проектирования, который позволяет управлять зависимостями между
Dependency Injection Dependency Injection (DI) — это паттерн проектирования, который позволяет управлять зависимостями между объектами. Он помогает разделить создание объектов от их использования и обеспечить более гибкую и тестируемую архитектуру программы. В DI объекты получают свои зависимости не напрямую, а через внешний источник, который их предоставляет. Этот источник называется контейнером внедрения зависимостей. Контейнер отвечает за создание и управление зависимостями, а объекты получают их через конструкторы, методы или свойства. ➡️ @cpp_geek

Готовы с нуля создавать телекоммуникационные решения для беспроводных мобильных сетей и сопутствующих услуг? 🧑‍💻 Отправляйт
+5
Готовы с нуля создавать телекоммуникационные решения для беспроводных мобильных сетей и сопутствующих услуг? 🧑‍💻 Отправляйте резюме до 19 октября и присоединяйтесь к команде YADRO Телеком! Как получить оффер за 3 дня? Листайте карточки выше — все подробности там! 💙 Оставляйте заявку — мы ждём именно вас!