👨💻 CppCourse — курс по C++ и объектно-ориентированному программированию!
Обучение идёт от работы с памятью, классов и наследования до шаблонов, STL, RAII, умных указателей и других возможностях C++. Теория закрепляется на учебном проекте, а ещё есть лабораторные, экзаменационные материалы и отдельный демо-проект с юнит-тестами, паттернами и архитектурой MVP.
Оставляю ссылочку: GitHub 📱
📣 C++ Ready | #репозиторий
Почему std::move сам ничего не перемещает?
Кажется, что вызов уже перенёс данные из одного объекта в другой.
На деле std::move только сообщает компилятору, что объект можно рассматривать как временный. Само перемещение происходит, когда другой код выбирает move-конструктор или move-присваивание.
std::string source = "report";
std::string target = std::move(source);
Здесь строка target забирает ресурсы source. После этого source остаётся валидной, но её содержимое не определено контрактом и часто оказывается пустым.
Поэтому нельзя писать логику, которая рассчитывает на конкретное значение после перемещения.
send(std::move(message));
// message больше не используем как прежнее значение
У std::move есть ещё одна ловушка. Перемещение из const-объекта обычно превращается в копирование, потому что move-конструктор не может менять источник.
const std::string name = "ready";
auto copy = std::move(name);
Такой код компилируется, но для std::string будет создана копия. Полезно применять std::move на последнем использовании объекта, когда прежнее значение действительно больше не нужно.
📣 C++ Ready | #совет
Большой разбор C++ механик!
Автор собрал масштабный материал по приёмам, которые встречаются в современном и легаси C++ коде. Внутри есть RAII, Scope Guard, умные указатели, move-семантика, шаблоны, исключения, Pimpl и десятки других идей с объяснением, откуда они появились.
В статье разбирают:
• как связывать владение ресурсом со временем жизни объекта
• почему noexcept влияет на производительность контейнеров
• где старые идиомы помогают понять код движков и библиотек
Продолжай читать на Habr
📣 C++ Ready | #статья
Почему std::move иногда вообще ничего не двигает?
std::move не перемещает объект сам по себе. Он только превращает выражение в rvalue-ссылку, чтобы компилятор мог выбрать move-конструктор или move-присваивание.
Но если объект const, перемещение может неожиданно превратиться в обычное копирование:
const std::string name = "ready";
std::string copy = std::move(name);
Кажется, что здесь будет move.
Но move-конструктор строки обычно принимает неконстантную rvalue-ссылку:
std::string(std::string&& other);
А из const объекта нельзя безопасно “забрать” внутреннее состояние, потому что это изменило бы объект.
Поэтому компилятор выбирает копирование:
const std::string name = "ready";
std::string result = std::move(name); // copy
Нормальное перемещение работает с неконстантным объектом:
std::string name = "ready";
std::string result = std::move(name); // move
После такого name остаётся валидным, но его содержимое уже не стоит использовать как прежнее значение:
std::cout << result << '\n';
std::move не гарантирует перемещение. Если объект const, чаще всего ты получишь копирование, просто записанное очень уверенным синтаксисом.
📣 C++ Ready | #совет
Шпаргалка по форматированию через библиотеку fmt!
На картинке собраны плейсхолдеры, именованные аргументы, выравнивание, ширина поля, точность, форматы чисел, строк, указателей и диапазонов.
Например, fmt::format собирает строку по шаблону, fmt::print выводит её сразу в консоль, а fmt::format_to пишет результат в готовый буфер или итератор.
Сохрани, чтобы не потерять!
📣 C++ Ready | #ресурс
Сравниваем два списка файлов на C++!
Допустим, есть ожидаемый список файлов релиза и список того, что реально попало в папку. Нужно быстро понять, какие файлы отсутствуют, не проходя вручную по каждому имени.
Для этого удобно использовать std::ranges::set_difference. Алгоритм работает с отсортированными диапазонами и сразу возвращает элементы, которые есть в первом списке, но отсутствуют во втором.
std::vector<std::string> expected = {"app", "config", "readme"};
std::vector<std::string> actual = {"app", "readme"};
Сначала приводим оба списка к одному порядку. Это важно, потому что set_difference не сортирует данные самостоятельно.
std::ranges::sort(expected);
std::ranges::sort(actual);
Теперь создаём контейнер для результата и передаём в него элементы, которые не нашлись во втором диапазоне.
std::vector<std::string> missing;
std::ranges::set_difference(expected, actual,
std::back_inserter(missing));
В missing останется только config. Так же можно искать лишние файлы, поменяв expected и actual местами.
for (const auto& name : missing) {
std::cout << "Missing: " << name << '\n';
}
Этот приём подходит для проверки состава релиза, конфигураций, прав доступа и любых двух наборов строк. Главное помнить про сортировку и не хранить дубликаты там, где они не имеют смысла.
📣 C++ Ready | #практика
Считаем медиану потока чисел на C++!
Представьте, что значения приходят постоянно, а медиану нужно знать после каждого нового числа. Полная сортировка на каждом шаге будет лишней.
В этой задаче:
• делим числа на две кучи
• поддерживаем размеры половин
• берём медиану из верхушек куч
Решение подходит для поступающих в реальном времени измерений, цен и задержек.
📣 C++ Ready | #задача
Визуализируем сортировку с SFML и C++20!
QuickSort проще понять, когда видно, как массив делится на части и элементы меняются местами. Автор берёт случайные числа, рисует их столбцами в окне SFML и связывает сортировку с обновлением изображения.
В статье разбирают:
• как подготовить массив и окно для визуализации
• как работает разбиение вокруг опорного элемента
• где рекурсия сортирует левую и правую части
Продолжай читать на Habr
📣 C++ Ready | #статья
Шпаргалка по ассоциативным контейнерам C++!
На картинке сравниваются set, map, unordered_set и unordered_map. Схемы показывают, где хранятся только ключи, где пары ключ-значение и чем упорядоченное дерево отличается от хеш-таблицы.
Например, map подходит, когда нужно обходить ключи по порядку, а unordered_map удобен для поиска без требования к порядку. Рядом есть короткие примеры вставки и доступа к элементам.
Сохрани, чтобы не потерять!
📣 C++ Ready | #ресурс
Ищем команды по префиксу на C++!
В CLI-приложении пользователь может помнить только начало команды. Сделаем поиск подсказок, который быстро находит подходящие варианты в отсортированном списке.
В этой задаче:
• сортируем команды
• находим начало через lower_bound
• собираем слова с нужным префиксом
Такой подход пригодится для автодополнения команд и названий настроек.
📣 C++ Ready | #задача
Как оплачивать зарубежные сервисы в 2026 году?
Можно бегать между посредниками и бояться блокировок после оплаты, а можно выпустить международную карту Lumio Pay и пользоваться любимыми сервисами без рисков.
— выпуск карты за 2 минуты
— лучший курс пополнения на рынке (у конкурентов на 20% выше)
— пополнение рублями или криптой
— чистые BIN карт, оплата без риска блокировок
Пока все ищут идеальное решение, оно у тебя перед глазами: @LumioPay
Знали, почему пути к файлам в C++ лучше собирать через std::filesystem::path?
Код может быстро обрастать ручными слешами, проверками расширения и поиском последнего разделителя:
std::string file = base + "/logs/app.log";
Это может работать, но чем больше операций с путём, тем сложнее поддерживать строковые трюки. std::filesystem::path даёт для таких операций отдельный тип:
namespace fs = std::filesystem;
fs::path file = fs::path(base) / "logs" / "app.log";
Оператор / соединяет части пути с учётом формата текущей платформы. Не приходится решать, какой разделитель вставлять между папками.
Части готового пути тоже можно получать без поиска символов:
auto name = file.filename();
auto folder = file.parent_path();
auto extension = file.extension();
Это удобно, например, когда нужно оставить только имя файла для лога или проверить расширение перед обработкой. Все три результата остаются объектами path, поэтому при выводе или передаче строковому API учитывайте требуемую кодировку.
Если в пути есть лишние точки или переходы в соседнюю папку, можно привести его к нормальной лексической форме:
fs::path clean = (fs::path("data") / "temp" / ".." / "report.txt")
.lexically_normal();
Здесь получится путь data/report.txt. Но lexically_normal не обращается к файловой системе и не проверяет, существует ли файл. Это преобразование записи пути, а не проверка безопасности.
Есть и важная ловушка. Если правая часть уже является абсолютным путём, она может заменить основу:
fs::path result = fs::path("/srv/app") / "/tmp/log.txt";
Поэтому пользовательский путь нельзя без проверки присоединять к базовой папке, если важно остаться внутри неё. Для обычного построения путей path убирает много ручной работы.
📣 C++ Ready | #совет
Можно ли собирать обычные C++-приложения в браузере?
Автор описывает систему, где прямо в браузере работает набор инструментов для сборки нативных приложений под разные платформы.
В статье разбирают:
• зачем понадобился единый слой над платформенными библиотеками
• как clang и lld удалось запустить через WebAssembly
• чем заменили привычные вызовы fork и внешних утилит
• как из браузера собирается и запускается приложение с графикой
Это история о реальных ограничениях кроссплатформенной сборки и о том.
Продолжай читать на Habr!
📣 C++ Ready | #статья
⚡️ Полный стек специалиста по кибербезопасности в одном бандле
Хватит собирать знания по крупицам. Мы объединили 5 флагманских прикладных курсов CyberYozh Academy в единую экосистему.
Все ключевые инструменты для работы в безопасности и автоматизации:
▪️ Базы данных: SQL для хакера
▪️ ОС и инфраструктура: Linux CyberPunk (с официальным дипломом сисадмина)
▪️ Практический пентест: HackerPoint + HackerPoint (Blue vs Red Team)
▪️ Кодинг и автоматизация: AI-помощники на Python
Вместо покупки разрозненных курсов по отдельности (~250 000 ₽), вы забираете полный комплект за 50 000 ₽.
⚠️В открытом доступе на сайте этого бандла нет - предложение доступно только по прямому запросу.
🦔Отправь промокод CReady в чат с менеджером, чтобы закрепить за собой скидку и узнать подробности:
👉@cyacademy_support
Почему unique_ptr::release() может оставить объект в памяти навсегда?
Обычно unique_ptr удаляет объект, когда владелец выходит из области видимости. Это одна из причин, почему его удобно возвращать из функций и хранить в классе:
auto ptr = std::make_unique<Widget>();
Но у unique_ptr есть метод release. Название звучит так, будто он освобождает память:
ptr.release();
На самом деле release освобождает unique_ptr от владения объектом. Он возвращает обычный указатель и оставляет ответственность за удаление вызывающему коду. Если результат проигнорировать, объект больше никто не удалит.
Когда нужен только временный доступ без передачи владения, используйте get:
Widget* borrowed = ptr.get();
use(*borrowed);
ptr по-прежнему владеет объектом. Сохранить borrowed после уничтожения ptr нельзя, зато вручную удалять его тоже не нужно.
Если объект нужно уничтожить прямо сейчас, подойдет reset:
ptr.reset();
После reset указатель станет пустым, а объект будет удалён через deleter, который хранит unique_ptr. Это не то же самое, что release.
Когда другая функция принимает unique_ptr, передайте владение явно:
consume(std::move(ptr));
get берёт указатель на время, reset удаляет объект, release отдаёт ответственность вам.
📣 C++ Ready | #совет