3 504
Подписчики
Нет данных24 часа
-27 дней
-2630 дней
Архив постов
3 503
Тема: std::optional и return value optimization (RVO)
Когда возвращаешь из функции
std::optional<T>, часто задумываешься о лишних копиях. Например, вот так:
std::optional<std::string> make_name(bool valid) {
if (valid) return "Женя";
return std::nullopt;
}
Миф: здесь всегда будет копирование строки.
Реальность: современные компиляторы отлично оптимизируют этот код благодаря RVO (Return Value Optimization). Если возвращаемое значение — временный объект, C++ может создать его сразу в том месте, куда он должен быть возвращён. Копий не будет!
Ещё интереснее с C++17: возвращение {} для std::optional<T> и "str" для строки — это всё равно RVO.
⚠️ Но если возвращаешь существующий объект:
std::optional<std::string> wrap(const std::string& s) {
return s; // здесь копия неизбежна
}
- тут RVO не поможет, потому что возвращаешь уже существующий объект, а не временный.
Вывод:
Не бойся возвращать большие объекты через std::optional! RVO спасает производительность, когда возвращаешь временные объекты.
➡️ @cpp_geek3 503
🚀 Открой для себя идеальный путь к лидерству с карьерным тестом от ОЭЗ «Алабуга»! 🌟
Мечтаете о карьере в крупной компании, где ваш потенциал раскроется на полную? Наш тест поможет вам определить вашу уникальную лидерскую роль. Может быть, именно вы станете тем лидером, который выведет команду на новый уровень?
После прохождения теста вы можете заполнить заявку и получить приглашение на эксклюзивную лидерскую программу. Участие в программе открывает реальные перспективы трудоустройства в ОЭЗ «Алабуга», предоставляя шанс начать путь к профессиональному признанию.
Сделайте первый шаг к своему будущему сегодня! Пройдите тест, подайте заявку и начните строить свою карьеру вместе с нами. 🎯
3 503
Пару фишек про шаблоны, которые могут спасти час дебага:
1. CTAD (Class Template Argument Deduction, C++17)
Не надо вручную указывать аргументы:
std::pair p(42, 3.14); // вместо std::pair<int, double> p(42, 3.14);
std::vector v = {1,2,3}; // компилятор сам выведет std::vector<int>
Помогает сократить код и избежать опечаток.
2. Fold-выражения (C++17) для арг-паков:
auto sum = [](auto... args){
return (args + ...); // ((a + b) + c) + ...
};
std::cout << sum(1,2,3,4); // 10
Позволяют писать операции над любым числом параметров без рекурсии.
3. SFINAE → Concepts (C++20)
Старый стиль через enable_if легко сломать:
template<class T>
std::enable_if_t<std::is_integral_v<T>, T>
foo(T x) { return x*2; }
С Concepts чище и понятнее:
template<std::integral T>
T foo(T x) { return x*2; }
4. CRTP (Static polymorphism)
Быстрее виртуалок и без RTTI:
template<class D>
struct Base {
void interface() { static_cast<D*>(this)->impl(); }
};
struct Derived : Base<Derived> {
void impl() { std::cout<<"OK\n"; }
};
Шаблоны — это не только про универсальность, но и про ясность кода. Освой тонкости, и они станут 🔧, а не головняком.
➡️ @cpp_geek3 503
👨💻🎓 Учишься в старших классах и мечтаешь о быстром старте карьеры в IT? Высший колледж информатики НГУ готовит программистов по передовым направлениям и предлагает программы обучения для выпускников 9 и 11 классов.
ВКИ при Новосибирском государственном университете — это качественное образование на базе престижного вуза, которое опирается на актуальные знания и современные методики обучения в сфере IT — от вайб-кодинга до LLM «тренажеров».
Почему ВКИ НГУ — это круто❓
✅ Современное оборудование и оснащение лабораторий, что позволяет изучать инновационные IT-технологии на самом высоком уровне и получать практические навыки в таких передовых областях, как робототехника, ИИ, IoT и проч.
✅ Передовые компетенции в IT-образовании: ВКИ НГУ первым среди образовательных учреждений за Уралом развернул опенсорсную большую языковую модель, которую официально рекомендует использовать в учебном процессе как студентам, так и преподавателям.
✅ Обучаем современным скиллам вайб-кодинга — готовим не просто «строителей кода», а архитекторов. Вайб-кодинг — новый метод программирования, когда код пишет нейросеть, а разработчик управляет ею с помощью команд, иногда буквально не касаясь клавиатуры. То есть в процессе используются LLM и ИИ, которые генерируют программный код на основе описания задачи на естественном языке.
✅ 130 бюджетных мест и скидки на обучение.
✅ 500 метров до Обского моря и 10 минут до живописного леса Академгородка с его белочками и научным вайбом.
На какие программы можно поступить❓
➡️ Компьютерные системы и комплексы (после 9 класса).
📌 Выпускники получат знания в таких прогрессивных областях, как «Интернет вещей», 3D-моделирование, промышленная автоматика, и смогут создавать управляющие компьютерные программы, разрабатывать программы микропроцессорных устройств и роботов, в том числе с применением ИИ.
➡️ Информационные системы и программирование (после 9 и 11 классов).
📌 Выпускники смогут заниматься разработкой и сопровождением IT-проектов широкого профиля. Они научаться создавать и интегрировать мобильные, desktop- и web-приложения с использованием современных инструментов, технологий и сред разработки, фреймворков и нейронных сетей.
➡️ Интеллектуальные интегрированные системы (после 9 класса).
📌 Новое направление, которое помимо программирования включает обучение работе с большими данными, методам ИИ, машинного обучения, IoT. Студенты получают уникальную возможность развивать навыки в проектировании и управлении сложными системами.
🗓 Когда подавать документы?
Приемная кампания стартует 20 июня. Прием документов продлится до 15 августа.
❗️ Все подробности и подача документов на сайте.
❓ Вопросы можно задать в официальной группе ВКИ НГУ ВКонтакте.
Реклама: Новосибирский государственный университет, ИНН 5408106490, erid: 2Vtzqv2Xkys
3 503
Тонкости STL, которые часто вылетают в продакшн:
1. Инвалидирование итераторов
При
vector::erase все итераторы от позиции удаления до end() становятся «битые». Чтобы безопасно отфильтровать и удалить элементы, пользуйтесь erase–remove идиомой:
auto it = std::remove_if(v.begin(), v.end(), [](int x){ return x < 0; });
v.erase(it, v.end());
remove_if сдвигает «хвост» вперёд, но не меняет размер контейнера.
2. reserve vs resize
* v.reserve(n) выделяет память, но не создаёт объектов → size() не меняется, можно безопасно push_back.
* v.resize(n) создаёт n элементов, инициализированных значениями по умолчанию.
3. Производительность std::distance
На random-access итераторах (например, vector) это O(1), а на bidirectional или forward (например, list) — O(n). Для списков используйте size() (C++11+) или считайте вручную в критичных местах.
4. emplace_back vs push_back
При сложных типах emplace_back может избежать лишнего копирования:
v.emplace_back(ctor_arg1, ctor_arg2);
// vs
v.push_back(MyType(ctor_arg1, ctor_arg2));
5. Памятка про компараторы
В set или map ваш компаратор должен задавать строгий-уровень-менее (operator<): если comp(a,b)==true, то comp(b,a) обязан быть false. Иначе — UB.
Быстро, без воды, но с пользой — проверяйте эти моменты в своём коде!
➡️ @cpp_geek3 503
🚀 Анонимные функции (лямбды) в C++
Лямбды — это удобные анонимные функции, которые можно объявлять прямо в коде. Вот ключевые фишки:
🔹 Базовый синтаксис
auto lambda = [] { /* тело функции */ };
Каждая лямбда имеет уникальный тип, даже если выглядит так же, как другая.
🔹Захват переменных
- По значению [x] — создаётся копия.
- По ссылке [&x] — работаем с оригиналом.
int a = 10, b = 10;
auto fn = [a, &b] {
a++; // Не влияет на оригинал
b++; // Меняет исходную переменную
};
🔹 Параметры и возвращаемое значение
auto sum = [](int x, int y) -> int { return x + y; };
Можно опустить -> int, если компилятор сам выведет тип.
🔹 Изменяемые лямбды (mutable)
Если захватываем по значению и хотим менять значение между вызовами:
int count = 0;
auto bump = [count]() mutable { ++count; };
🔹Обобщённые лямбды (C++14+)
Можно использовать auto для параметров:
auto sum = [](auto x, auto y) { return x + y; };
🔹Условная компиляция (if constexpr)
Позволяет обрабатывать разные типы по-разному:
auto print = [](auto x) {
if constexpr (std::is_same_v) {
std::cout << «int: " << x;
}
};
💡 Вывод:
Лямбды делают код лаконичнее, поддерживают захват переменных, обобщённые вычисления и даже constexpr-логику. Отлично заменяют мелкие функции и функторы.
➡️ @cpp_geek3 503
✅ Чек-лист: Линейные структуры данных в C++
Линейные структуры данных — фундамент программирования на C++. Правильный выбор структуры может значительно повысить эффективность вашего кода.
🎯 Векторы (std::vector)
✓ Используйте
reserve() для предварительного выделения памяти, когда примерно известен размер
✓ Применяйте push_back() для добавления элементов и pop_back() для удаления с конца
✓ Доступ по индексу выполняется за O(1) с помощью оператора []
✓ Используйте at() вместо [] для проверки границ массива
🎯 Списки (std::list)
✓ Отдавайте предпочтение при частых вставках/удалениях в середине
✓ Используйте splice() для эффективного перемещения элементов между списками
✓ Помните, что прямой доступ по индексу невозможен — только итерация
✓ Двунаправленные итераторы позволяют двигаться как вперед, так и назад
🎯 Очереди и стеки (std::queue, std::stack)
✓ Стек (LIFO): используйте push() для добавления и pop() для извлечения
✓ Очередь (FIFO): применяйте push() для добавления и pop() для извлечения
✓ Функция front() позволяет посмотреть первый элемент без удаления
✓ Обе структуры являются адаптерами и построены на других контейнерах
🎯 Массивы (std::array)
✓ Используйте для данных фиксированного размера, известного на этапе компиляции
✓ Более эффективны чем векторы для неизменяемых данных
✓ Поддерживают STL-алгоритмы (sort, find и др.)
✓ Проверяйте границы с функцией at() во избежание ошибок доступа
➡️ @cpp_geek3 503
How to: убираем типы с помощью std::decay_t
std::decay_t — один из самых полезных type traits в C++. Он имитирует процесс передачи параметра по значению, «разрушая» исходный тип.
🔄 Что именно делает decay_t?
• Убирает cv-квалификаторы
• Превращает ссылки в соответствующие типы без ссылок
• Преобразует массивы в указатели
• Преобразует функции в указатели на функции
💻 Пример:
#include <type_traits>
#include <iostream>
int main() {
// const int& -> int
static_assert(std::is_same_v<std::decay_t<const int&>, int>);
// int[10] -> int*
static_assert(std::is_same_v<std::decay_t<int[10]>, int*>);
// void(int) -> void(*)(int)
static_assert(std::is_same_v<std::decay_t<void(int)>, void(*)(int)>);
std::cout << "All assertions passed!" << std::endl;
}
🚀 Где это используется?
• В шаблонном программировании для упрощения работы с типами
• В std::make_shared и std::make_unique для определения типа создаваемого объекта
• При написании обобщенного кода, где нужна правильная дедукция типов
🔍 И да, название «decay» («разрушение») действительно отражает суть — тип «разрушается» до базового представления!
➡️ @cpp_geek3 503
std::move ничего не двигает 🤯
Вот типичная ошибка, которая встречается даже у опытных:
std::string foo() {
std::string s = "hello";
return std::move(s); // ❌
}
Кажется, что std::move здесь «ускоряет» возврат. Но это зло. На самом деле, компилятор и без std::move применяет Return Value Optimization (RVO) и возвращает s без копирования. А вот std::move ломает RVO — теперь вызывается перемещающий конструктор, и компилятор не может это оптимизировать.
Результат:
* return s; — возможно, вообще без затрат (RVO).
* return std::move(s); — гарантированно перемещение (дороже, чем RVO).
🔑 Правило: никогда не пиши std::move при возврате локальной переменной по значению. Доверься компилятору.
Когда std::move действительно нужен? Например:
void bar(std::string&& s) {
auto local = std::move(s); // перемещаем из rvalue-ссылки
}
Здесь всё логично: мы явно говорим, что хотим «украсть» содержимое.
Вывод: std::move — это не перемещение, а обещание, что объект можно обобрать. А перемещать будет уже компилятор.
➡️ @cpp_geek3 503
Почему
std::move может не сработать, как ты ожидал
Всё просто? Хочешь передать объект по move — вызываешь std::move(obj) и думаешь, что теперь точно будет перемещение. Но не всё так однозначно.
void foo(std::string s) {
std::string local = std::move(s);
}
Выглядит, будто s перемещается в local. Но на практике — нет. Здесь копирование. Почему?
s — это lvalue, несмотря на std::move в правой части. А значит, выбирается std::string конструктор копирования, если только он не удалён.
Чтобы реально переместить, нужно явно вызвать std::move:
std::string local = std::move(s); // ОК — move-конструктор
Но будь осторожен:
std::string getStr() {
std::string tmp = "hello";
return std::move(tmp); // ❌ Не всегда нужно!
}
Здесь std::move ломает RVO (Return Value Optimization). Компилятор мог бы вернуть tmp без перемещения, вообще без копий. А std::move мешает, заставляя делать move-конструктор.
Выводы:
– std::move не двигает, он обещает, что ты больше не тронешь объект
– Будь осторожен с std::move в return
– Не забудь, что lvalue остаётся lvalue, даже если ты его "обернул" std::move
➡️ @cpp_geek3 503
C++: зачем
[[nodiscard]] на bool — и почему это важно
Когда функция возвращает bool, часто возникает соблазн проигнорировать результат:
is_valid(user); // ничего не делает!
А теперь представьте, что is_valid() проверяет критическое условие. Без проверки — баг, возможно даже security-уязвимость.
Чтобы защититься от такого, с C++17 есть [[nodiscard]]:
[[nodiscard]] bool is_valid(const User& user);
Теперь, если результат проигнорировать — компилятор предупредит:
warning: ignoring return value of 'is_valid', declared with attribute 'nodiscard'Можно ещё улучшить читаемость — использовать
[[nodiscard("Must check if user is valid")]], чтобы компилятор написал пояснение в варнинге (начиная с C++20).
🔥 Лайфхак: ставьте [[nodiscard]] на все функции, где игнорирование результата — это почти всегда ошибка. Особенно на:
* проверки (is_...)
* операции с возможным фейлом (try_..., parse_...)
* RAII-объекты с флагами состояния
Не ленитесь — [[nodiscard]] спасает от тонких багов и делает код надёжнее.
➡️ @cpp_geek3 503
🚀 Подборка 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/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
3 503
📌 Сегодня расскажу вам о проблеме, которую часто упускают: небезопасный доступ к std::vector по указателю после push_back.
Смотрим код:
std::vector<MyStruct> vec;
vec.reserve(10); // вроде как "гарантируем", что ничего не сломается
MyStruct* ptr = &vec[0];
vec.push_back(MyStruct{});
// BOOM! ptr теперь может быть невалиден
💥 Даже несмотря на reserve(10), контейнер имеет право перераспределить память при любом push_back, если по каким-то причинам решил, что нужно. Например, при нарушении alignment или внутренней оптимизации.
🔒 Что делать безопасно:
* Никогда не храните указатели или ссылки на элементы std::vector, если планируете его изменять.
* Если нужно, используйте индекс:
size_t index = 0;
vec.push_back(...);
use(vec[index]);
* Или используйте std::list / std::deque, если вам действительно нужны устойчивые указатели.
🧠 Это классический источник UB (Undefined Behavior), особенно в старых проектах, где кто-то “оптимизировал” память, сохранив указатель.
Поделитесь, попадались ли вам такие баги? 👇
➡️ @cpp_geek3 503
🧵 Сегодня покажу вам простой, но полезный приём для оптимизации копирования std::vector.
Часто вижу такую конструкцию:
std::vector<int> result;
result = getVector();
Если getVector() возвращает временный объект, то копирование можно избежать, используя std::move или Return Value Optimization (RVO).
Но вот интересное: если вы точно знаете, что копия не нужна, используйте std::vector::swap с временным объектом:
std::vector<int> result;
std::vector<int> tmp = getVector();
result.swap(tmp);
Почему это может быть лучше?
🔸 Быстрая реализация через указатели.
🔸 Не вызывает лишние аллокаторы.
🔸 Не зависит от move конструктора.
🔸 Гарантированно не бросает исключений, если swap noexcept (что обычно так).
В новых компиляторах result = std::move(tmp) даст тот же эффект, но swap — это старый добрый способ, который работает предсказуемо.
🧠 Подумайте, где можно применить это у себя — особенно если работаете с большими контейнерами.
➡️ @cpp_geek3 503
Сегодня хочу показать вам один из приёмов, который часто выручает в реальной разработке на C++ — оборачивание C API в безопасные RAII-объекты.
Многие библиотеки на C (например, OpenSSL, SQLite, libpng) требуют вручную управлять ресурсами — открывать, закрывать, аллоцировать и освобождать. Это источник ошибок: забыли
free(), упустили close(), получили утечку памяти или файлового дескриптора.
В C++ мы можем обернуть такие ресурсы в класс с аккуратным деструктором:
class FileHandle {
public:
explicit FileHandle(FILE* file) : file_(file) {}
~FileHandle() {
if (file_) {
fclose(file_);
}
}
FILE* get() const { return file_; }
private:
FILE* file_;
};
Теперь, даже если функция выбросит исключение или произойдет выход из области видимости, файл закроется автоматически!
Такие классы легко комбинировать с std::unique_ptr через кастомные делетеры для ещё большей безопасности.
Не забывайте: RAII (Resource Acquisition Is Initialization) — один из важнейших паттернов для профессионального C++.
➡️ @cpp_geek3 503
🚀 Подборка 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/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
3 503
🔥 Сегодня я расскажу про одно коварное поведение
std::vector, которое часто становится причиной багов и утечек.
📌 Проблема: Удаление элементов в цикле
Многие делают так:
std::vector<int> v = {1, 2, 3, 4, 5};
for (size_t i = 0; i < v.size(); ++i) {
if (v[i] % 2 == 0) {
v.erase(v.begin() + i);
}
}
Но это ошибка! После erase вектор сдвигает все элементы, и индекс i указывает уже не на тот элемент. В результате часть значений пропускается.
✅ Правильный способ — использовать итераторы:
auto it = v.begin();
while (it != v.end()) {
if (*it % 2 == 0)
it = v.erase(it);
else
++it;
}
Так вы не теряете элементы и не получаете неопределённое поведение.
🧠 Советы:
- Всегда помните, что erase инвалидирует итераторы и индексы.
- Если хотите удалять по условию — лучше использовать std::remove_if + erase.
v.erase(std::remove_if(v.begin(), v.end(), [](int x) {
return x % 2 == 0;
}), v.end());
➡️ @cpp_geek3 503
🧠 Как static в C++ помогает бороться с неожиданностями
Сейчас покажу вам интересную особенность ключевого слова
static в контексте функций — то, что часто забывают даже опытные разработчики.
Представим простую ситуацию:
void logCall() {
int counter = 0;
counter++;
std::cout << "Called " << counter << " times\n";
}
Кажется, всё хорошо… Но функция всегда выводит Called 1 times, потому что переменная counter создаётся заново при каждом вызове.
Теперь добавим static:
void logCall() {
static int counter = 0;
counter++;
std::cout << "Called " << counter << " times\n";
}
А вот теперь магия — переменная counter сохраняет своё значение между вызовами! Это отличный способ реализовать простой счётчик, кэш или ленивую инициализацию прямо в функции.
📌 Важно: static делает переменную локальной по области видимости, но глобальной по времени жизни.
А вы где применяли static неожиданным образом? Делитесь в комментариях! 👇
➡️ @cpp_geek3 503
💡 Сегодня покажу вам способ, как удобно логировать enum-значения в C++, не превращая код в кашу из
switch и if.
📌 Проблема: у вас есть enum, и вы хотите красиво выводить его в лог или std::cout, но стандартно C++ этого не умеет.
Например:
enum class Status {
Ok,
Error,
Timeout
};
Обычно вы пишете:
std::string to_string(Status s) {
switch(s) {
case Status::Ok: return "Ok";
case Status::Error: return "Error";
case Status::Timeout: return "Timeout";
}
return "Unknown";
}
Но есть способ проще и без switch — с помощью макроса и X-макросов:
#define STATUS_ENUM(XX) \
XX(Ok) \
XX(Error) \
XX(Timeout)
enum class Status {
#define GENERATE_ENUM(name) name,
STATUS_ENUM(GENERATE_ENUM)
#undef GENERATE_ENUM
};
inline const char* to_string(Status s) {
switch(s) {
#define GENERATE_CASE(name) case Status::name: return #name;
STATUS_ENUM(GENERATE_CASE)
#undef GENERATE_CASE
default: return "Unknown";
}
}
Теперь достаточно один раз задать список значений — и не нужно вручную синхронизировать enum и to_string().
✅ Такой подход легко масштабируется.
✅ Удобно для логирования, отладки и сериализации.
Пользуйтесь!
➡️ @cpp_geek3 503
Сегодня покажу вам полезную вещь, которую часто упускают даже опытные C++ разработчики - Альтернативные способы инициализации
std::vector.
🔹 std::vector: Инициализация — больше, чем просто {}
Многие используют векторы так:
std::vector<int> v = {1, 2, 3};
Но есть и другие варианты, которые помогут сделать код выразительнее, а в некоторых случаях — эффективнее.
🔸 1. Инициализация с количеством элементов и значением
std::vector<int> v(5, 10); // 5 элементов по 10
🔥 Часто полезно, когда нужен предзаполненный буфер.
🔸 2. С использованием std::fill
std::vector<int> v(10);
std::fill(v.begin(), v.end(), 7);
✅ Удобно, когда вектор уже создан, но нужно всё заполнить определённым значением.
🔸 3. std::generate и std::iota
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1); // 1, 2, 3, ..., 10
🚀 Идеально подходит, когда нужно создать диапазон значений.
🔸 4. Из другой коллекции (через итераторы)
std::list<int> lst = {4, 5, 6};
std::vector<int> v(lst.begin(), lst.end());
🔄 Позволяет гибко конвертировать контейнеры.
🔸 5. Через reserve + emplace_back
std::vector<std::pair<int, int>> v;
v.reserve(3);
v.emplace_back(1, 2);
v.emplace_back(3, 4);
v.emplace_back(5, 6);
🔧 Отлично, когда важна производительность и хочется избежать лишнего копирования.
✅ Совет: Не забывайте про reserve, если знаете итоговый размер вектора — избежите лишних реаллокаций.
Надеюсь, вы узнали что-то новое. Поделитесь, какие приёмы чаще используете вы?
➡️ @cpp_geek