C/C++ Ready | Программирование


Гео и язык канала: Россия, Русский
Категория: Технологии


Авторский канал по разработке на C и C++.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Cотрудничество: @energy_c
РКН: https://clck.ru/3QREHc

Зарегистрирован в РКН
Связанные каналы  |  Похожие каналы

Гео и язык канала
Россия, Русский
Категория
Технологии
Статистика
Фильтр публикаций




Шпаргалка по std::variant в C++!

На картинке показано, как один объект хранит значение одного из нескольких заранее известных типов. Видно, что у variant есть активная альтернатива, её индекс и место под самый большой из перечисленных типов.

Сохрани, чтобы не потерять!

📣 C++ Ready | #ресурс


Проверяем числовой аргумент командной строки в C++!

Допустим, утилита принимает номер порта. Преобразовать строку в число мало, нужно отклонить пустой ввод, лишние символы и значение вне допустимого диапазона. Иначе строка вроде 8080abc может превратиться в 8080.

Возьмём строку из аргументов программы и подготовим границы для разбора:
std::string_view input = argv[1];
const char* first = input.data();
const char* last = first + input.size();

Перед чтением argv[1] проверь, что argc равен 2. Пустую строку тоже лучше сразу отклонить, чтобы сообщение об ошибке было понятным.

Теперь вызовем std::from_chars. Он не создаёт временную строку и сообщает результат через код ошибки:
int port = 0;
auto [next, error] = std::from_chars(first, last, port);

Одного успешного преобразования недостаточно. Проверим, что функция действительно дошла до конца входа:
if (error != std::errc{} || next != last) {
std::cerr 65535) {
std::cerr


Почему unique_ptr::release() может оставить объект в памяти навсегда?

Обычно unique_ptr удаляет объект, когда владелец выходит из области видимости. Это одна из причин, почему его удобно возвращать из функций и хранить в классе:
auto ptr = std::make_unique();

Но у 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 | #совет


Можно ли собирать обычные C++-приложения в браузере?

Автор описывает систему, где прямо в браузере работает набор инструментов для сборки нативных приложений под разные платформы.

В статье разбирают:
• зачем понадобился единый слой над платформенными библиотеками
• как clang и lld удалось запустить через WebAssembly
• чем заменили привычные вызовы fork и внешних утилит
• как из браузера собирается и запускается приложение с графикой

Это история о реальных ограничениях кроссплатформенной сборки и о том.

Продолжай читать на Habr!


📣 C++ Ready | #статья


Знали, почему пути к файлам в 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++!

В CLI-приложении пользователь может помнить только начало команды. Сделаем поиск подсказок, который быстро находит подходящие варианты в отсортированном списке.

В этой задаче:
• сортируем команды
• находим начало через lower_bound
• собираем слова с нужным префиксом


Такой подход пригодится для автодополнения команд и названий настроек.

📣 C++ Ready | #задача




Шпаргалка по ассоциативным контейнерам C++!

На картинке сравниваются set, map, unordered_set и unordered_map. Схемы показывают, где хранятся только ключи, где пары ключ-значение и чем упорядоченное дерево отличается от хеш-таблицы.

Например, map подходит, когда нужно обходить ключи по порядку, а unordered_map удобен для поиска без требования к порядку. Рядом есть короткие примеры вставки и доступа к элементам.

Сохрани, чтобы не потерять!

📣 C++ Ready | #ресурс


Визуализируем сортировку с SFML и C++20!

QuickSort проще понять, когда видно, как массив делится на части и элементы меняются местами. Автор берёт случайные числа, рисует их столбцами в окне SFML и связывает сортировку с обновлением изображения.

В статье разбирают:
• как подготовить массив и окно для визуализации
• как работает разбиение вокруг опорного элемента
• где рекурсия сортирует левую и правую части

Продолжай читать на Habr


📣 C++ Ready | #статья


Считаем медиану потока чисел на C++!

Представьте, что значения приходят постоянно, а медиану нужно знать после каждого нового числа. Полная сортировка на каждом шаге будет лишней.

В этой задаче:
• делим числа на две кучи
• поддерживаем размеры половин
• берём медиану из верхушек куч


Решение подходит для поступающих в реальном времени измерений, цен и задержек.

📣 C++ Ready | #задача




Сравниваем два списка файлов на C++!

Допустим, есть ожидаемый список файлов релиза и список того, что реально попало в папку. Нужно быстро понять, какие файлы отсутствуют, не проходя вручную по каждому имени.

Для этого удобно использовать std::ranges::set_difference. Алгоритм работает с отсортированными диапазонами и сразу возвращает элементы, которые есть в первом списке, но отсутствуют во втором.
std::vector expected = {"app", "config", "readme"};
std::vector actual = {"app", "readme"};

Сначала приводим оба списка к одному порядку. Это важно, потому что set_difference не сортирует данные самостоятельно.
std::ranges::sort(expected);
std::ranges::sort(actual);

Теперь создаём контейнер для результата и передаём в него элементы, которые не нашлись во втором диапазоне.
std::vector missing;
std::ranges::set_difference(expected, actual,
std::back_inserter(missing));

В missing останется только config. Так же можно искать лишние файлы, поменяв expected и actual местами.
for (const auto& name : missing) {
std::cout


Шпаргалка по форматированию через библиотеку fmt!

На картинке собраны плейсхолдеры, именованные аргументы, выравнивание, ширина поля, точность, форматы чисел, строк, указателей и диапазонов.

Например, fmt::format собирает строку по шаблону, fmt::print выводит её сразу в консоль, а fmt::format_to пишет результат в готовый буфер или итератор.

Сохрани, чтобы не потерять!

📣 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


Большой разбор C++ механик!

Автор собрал масштабный материал по приёмам, которые встречаются в современном и легаси C++ коде. Внутри есть RAII, Scope Guard, умные указатели, move-семантика, шаблоны, исключения, Pimpl и десятки других идей с объяснением, откуда они появились.

В статье разбирают:
• как связывать владение ресурсом со временем жизни объекта
• почему noexcept влияет на производительность контейнеров
• где старые идиомы помогают понять код движков и библиотек

Продолжай читать на Habr


📣 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 | #совет


👨‍💻 CppCourse — курс по C++ и объектно-ориентированному программированию!

Обучение идёт от работы с памятью, классов и наследования до шаблонов, STL, RAII, умных указателей и других возможностях C++. Теория закрепляется на учебном проекте, а ещё есть лабораторные, экзаменационные материалы и отдельный демо-проект с юнит-тестами, паттернами и архитектурой MVP.

Оставляю ссылочку: GitHub 📱


📣 C++ Ready | #репозиторий


Почему setprecision не всегда означает количество знаков после точки?

В C++ для форматирования дробных чисел часто используют std::setprecision. На первый взгляд кажется, что он задаёт количество цифр после запятой.

Но без std::fixed это не так:
std::cout



Показано 20 последних публикаций.