C/C++ Ready | Программирование
15.8K subscribers
1.5K photos
94 videos
751 links
Авторский канал по разработке на C и C++.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Cотрудничество: @energy_c

РКН: https://clck.ru/3QREHc
Download Telegram
Почему 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤6🔥3
Большой разбор C++ механик!

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

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

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍6🔥3
Почему 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍5🔥3
Шпаргалка по форматированию через библиотеку fmt!

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

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

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤5🔥2
Сравниваем два списка файлов на 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 | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍5🔥2
Считаем медиану потока чисел на C++!

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

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


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

📣 C++ Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥7👍5😁1
Визуализируем сортировку с SFML и C++20!

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

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

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤6👎2🔥2
Шпаргалка по ассоциативным контейнерам C++!

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

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

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5🔥3
Ищем команды по префиксу на C++!

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

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


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

📣 C++ Ready | #задача
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥5👍3
Знали, почему пути к файлам в 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍4🔥4