cpp_ready | Unsorted

Telegram-канал cpp_ready - C/C++ Ready | Программирование

-

Авторский канал по разработке на C и C++. Ресурсы, обучения, задачи, шпаргалки. Ежедневно информация пополняется! Автор: @energy_it

Subscribe to a channel

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

Удаление элементов без erase-remove идиомы: `std::erase_if`

Когда нужно удалить элементы из контейнера по условию, в старом C++ часто использовали связку std::remove_if + erase. Работает, но выглядит шумно и не сразу читается.

В C++20 для этого есть std::erase_if.

Например, удалим все отрицательные значения из std::vector:

std::vector<int> values{3, -1, 7, -5, 10};

std::erase_if(values, [](int x) {
return x < 0;
});


После этого в контейнере останутся только положительные значения:
for (int x : values) {
std::cout << x << ' ';
}
// 3 7 10


Без std::erase_if пришлось бы писать длиннее:
values.erase(
std::remove_if(values.begin(), values.end(), [](int x) {
return x < 0;
}),
values.end()
);


Новая версия лучше показывает намерение: мы не “переставляем элементы и потом стираем хвост”, а просто удаляем всё, что подходит под условие.

std::erase_if работает не только с std::vector, но и с другими стандартными контейнерами:
std::map<std::string, int> counters{
{"ok", 10},
{"errors", 0},
{"warnings", 3}
};

std::erase_if(counters, [](const auto& item) {
return item.second == 0;
});


Так можно аккуратно чистить контейнеры без ручных циклов и лишнего служебного кода.

🔥 std::erase_if делает удаление по условию коротким и читаемым: одно действие — одна понятная строка.

📣 C++ Ready | #практика

Читать полностью…

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

☕️ Code․mu Tasker — бесплатный практический задачник по плюсам!

Здесь собрано 100 упражнений, распределённых по 10 уровням, которые помогут вам отработать базовые конструкции языка, принципы ООП, работу с библиотекой STL, алгоритмы и многое другое.

📌 Оставляю ссылочку: code.mu

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

Читать полностью…

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

📂 Напоминалка по памяти и накопителям!

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

На картинке — основные типы памяти и storage: RAM, ROM, SRAM, DRAM и др.

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

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

Читать полностью…

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

📂 Напоминалка для работы с OOP Design Patterns!

Например, Factory помогает делегировать создание объектов, а Observer — удобно реализовать систему подписок и событий.

На картинке — 9 самых нужных паттернов, которые часто встречаются в реальных проектах и архитектуре.

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

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

Читать полностью…

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

🔥База платных курсов и книг по программированию на весь 2026 год!🔥

Канал новый, потому что слишком много людей ждут халявы.

Тут всё, что обычно стоит тысячи:
— Авторские курсы, которые не найти в открытом доступе
— Самые свежие книги для старта
— Всё, что нужно, чтобы за полгода вырасти от мидла до сеньора

➡️ Залетайте, пока есть доступ!

Читать полностью…

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

Почему lambda с [=] может работать не так, как ты ожидаешь?

Потому что [=] копирует только локальные переменные из текущей области видимости.
Но если внутри метода класса ты обращаешься к полям объекта, на самом деле захватывается не сам объект целиком, а указатель this.

В таком коде:


cpp id="r8n2fs"
pool.enqueue([=] {
process(data_);
});


может казаться, что data_ безопасно скопирован внутрь lambda. Но это не так.

Фактически lambda использует this, а значит обращается к полю исходного объекта.
Если к моменту выполнения задачи объект уже уничтожен, код получит висячий указатель и undefined behavior.

Из-за этого баг особенно неприятный:
• внешне всё выглядит как “захват по значению”
• код может долго работать нормально
• а потом упасть в асинхронном сценарии, где объект уже не живёт


Если нужен именно снимок данных на момент создания lambda, лучше захватывать его явно:

cpp id="x1kz7d"
auto data = data_;
pool.enqueue([data] {
process(data);
});


А если нужен сам объект, важно явно контролировать его lifetime.

🔥[=] внутри метода класса не копирует поля объекта автоматически. Чаще всего ты захватываешь this, а не данные.

📣 C++ Ready | #совет

Читать полностью…

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

👩‍💻 Рассмотрим std::bitset — быстрый и понятный способ работы с битами!

С его помощью можно удобно хранить и обрабатывать флаги, состояния и биты без возни с ручными масками и побитовыми операциями. Это особенно полезно в системном программировании, играх и embedded-разработке.

📣 C++ Ready | #шпора

Читать полностью…

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

Почему после push_back() нельзя слепо использовать старый итератор?

Потому что std::vector хранит элементы в непрерывной области памяти.
Если при добавлении нового элемента текущей capacity уже не хватает, вектор перевыделяет память и переносит элементы в новое место.

После этого все итераторы, ссылки и указатели на старые элементы становятся невалидными.

В таком коде:

std::vector<int> v = {1, 2, 3};

auto it = v.begin();
v.push_back(4);

std::cout << *it << "\n";


it мог указывать на элемент в старом буфере памяти.
Если во время push_back() произошел reallocation, разыменование it — это уже undefined behavior.

Из-за этого баг особенно неприятный: код может

* работать “нормально” на маленьких примерах,
* ломаться только на других данных,
* проявляться нестабильно и не сразу.

Если после изменения vector тебе снова нужен итератор, его лучше получить заново.
А если хочешь уменьшить шанс перевыделения памяти, можно заранее вызвать reserve().

🔥 У vector итераторы живут только до тех пор, пока контейнер не изменил свое хранилище.

📣 C++ Ready | #совет

Читать полностью…

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

Не копировать объект, а просто обменять: std::swap как базовый инструмент

Иногда нужно просто поменять значения двух переменных местами. Вручную это обычно делают через временную переменную, но в C++ для этого уже есть готовый и понятный инструмент — std::swap.

Простой пример:

int a = 10;
int b = 20;

std::swap(a, b);

std::cout << a << ' ' << b << '\n';


После вызова значения переменных меняются местами:
a == 20
b == 10

То же самое работает не только с числами, но и с контейнерами:
std::vector<int> x{1, 2, 3};
std::vector<int> y{4, 5};

std::swap(x, y);

std::cout << x.size() << ' ' << y.size() << '\n';


Такой обмен обычно дешевле и чище, чем ручное переприсваивание. А главное — сразу видно намерение: мы не “что-то присваиваем”, а именно меняем объекты местами.

🔥 std::swap делает код проще и выразительнее: обмен значений — одной строкой и без лишнего шума.

📣 C++ Ready | #практика

Читать полностью…

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

Почему push_back() во время обхода vector может привести к багу?

Потому что при добавлении нового элемента std::vector может перевыделить память. А после этого все итераторы, ссылки и указатели на его элементы становятся невалидными.

Проблема в том, что range-based for тоже опирается на итераторы. И если внутри цикла вызвать:

v.push_back(5);


контейнер может переехать в другую область памяти. Тогда цикл продолжит работу уже с невалидными итераторами, а это undefined behavior.

То есть внешне код выглядит безобидно, но в реальности может:

• работать “случайно нормально”
• пропускать элементы
• падать
• давать нестабильное поведение

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

🔥 У vector добавление элемента может инвалидировать итераторы. Менять контейнер во время его обхода нужно очень осторожно.

📣 C++ Ready | #совет

Читать полностью…

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

Разбираем безопасное побитовое преобразование типов!

Сейчас научимся преобразовывать данные одного типа в другой без неопределённого поведения — с помощью функции std::bit_cast.

Сначала подключим необходимые библиотеки из стандартной поставки:

#include <bit>      // std::bit_cast
#include <cstdint> // uint32_t
#include <iostream>
#include <iomanip> // std::hex, std::setw, std::setfill


Теперь создадим число с плавающей точкой и преобразуем его в uint32_t, чтобы увидеть его внутреннее битовое представление:
float value = 3.1415926f;
uint32_t raw = std::bit_cast<uint32_t>(value);

std::cout << "Биты числа: 0x"
<< std::hex << std::setw(8) << std::setfill('0') << raw << '\n';


Преобразуем обратно, чтобы убедиться, что значение не потеряно:
float restored = std::bit_cast<float>(raw);
std::cout << std::dec << "Восстановлено: " << restored << '\n';


Результат при запуске программы:
Биты числа: 0x40490fda  
Восстановлено: 3.14159


🔥 Таким образом ты можешь безопасно перепаковывать данные между типами одинакового размера — без UB, memcpy и хаков.

📣 C++ Ready | #практика

Читать полностью…

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

👩‍💻 Разберём циклы с диапазоном и auto — способ проходить по контейнеру без индексов и явных итераторов!

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

📣 C++ Ready | #шпора

Читать полностью…

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

Меньше .first и .second: разбираем pair и tuple по-человечески!

Когда работаешь с std::pair, std::tuple или элементами std::map, код быстро зарастает обращениями вроде .first, .second и std::get<0>(). Читать это неудобно, особенно если таких мест много.

В C++17 для этого есть structured bindings. Они позволяют сразу разложить объект на именованные переменные.

Например, так можно пройтись по std::map:

#include <iostream>
#include <map>
#include <string>

std::map<std::string, int> scores{
{"alice", 10},
{"bob", 20}
};

for (const auto& [name, score] : scores) {
std::cout << name << ": " << score << '\n';
}


Без structured bindings пришлось бы писать менее выразительно:
for (const auto& item : scores) {
std::cout << item.first << ": "
<< item.second << '\n';
}


То же самое работает и с std::pair:
std::pair p{"error", 500};

auto [text, code] = p;
std::cout << text << ' ' << code << '\n';


Код становится короче и понятнее: вместо технических .first и .second появляются нормальные имена переменных, которые сразу передают смысл.

🔥 Structured bindings делают код читаемее: меньше служебного шума, больше понятных имён.

📣 C++ Ready | #практика

Читать полностью…

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

Как shared_ptr может привести к утечке памяти?

Потому что подсчет ссылок не умеет сам разрывать циклы.

Если два объекта держат друг друга через std::shared_ptr, их счетчики ссылок никогда не станут равны нулю. Даже когда внешний код уже “отпустил” оба объекта, они продолжают владеть друг другом.

Например, в такой схеме:

struct A {
std::shared_ptr<B> b;
};

struct B {
std::shared_ptr<A> a;
};


объект A владеет B, а B владеет A.
Получается замкнутый круг: оба объекта остаются в памяти, потому что у каждого все еще есть хотя бы один владелец.

Именно поэтому shared_ptr не гарантирует автоматическое освобождение памяти во всех случаях.

Чтобы разорвать цикл, одна из ссылок должна быть не владеющей:
struct B {
std::weak_ptr<A> a;
};


std::weak_ptr не увеличивает счетчик владения, поэтому цикл исчезает, и объекты могут быть корректно уничтожены.

🔥 shared_ptr считает владельцев, но не умеет сам разрывать циклы. Для этого нужен weak_ptr.

📣 C++ Ready | #совет

Читать полностью…

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

✍️ CyberForum — крупнейшее сообщество разработчиков с разделами по C++ и C#!

Форум, где можно обсуждать задачи, получать помощь и разбирать кейсы из разработки. Есть активные разделы по C++ и C#: обсуждение синтаксиса, разбор ошибок, советы по обучению и практическая помощь. Форум можно использовать как источник знаний, особенно когда требуется разобраться в конкретной задаче или посмотреть, как её решают другие разработчик.

📌 Оставляю ссылочку: cyberforum.ru

📣 C++ Ready | #сайт

Читать полностью…

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

❤️ Free Programming Books — огромная коллекция бесплатных книг по программированию!

В этом репозитории собраны десятки книг по разным языкам и направлениям, таким как C/C++ и многое другое. Всё разложено по категориям, поэтому можно быстро найти нужную тему. Здесь есть как базовые учебники по синтаксису и указателям, так и более серьёзные материалы по памяти, низкоуровневой работе и системному программированию.

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


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

Читать полностью…

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

Почему std::optional<T> часто понимают неправильно?

Потому что optional выглядит как “объект, которого может не быть”, и из-за этого его легко мысленно приравнять к указателю. Но это другая модель.

std::optional<T> хранит значение внутри себя.
То есть если значение есть, объект T находится прямо внутри optional, а не где-то отдельно в памяти.

Например:

std::optional<std::string> name = "Gus";


здесь optional не указывает на строку — он содержит строку внутри себя.

Из-за этого у optional другая семантика:

• копирование optional копирует и само значение
• перемещение optional перемещает значение
• optional не подходит как замена ссылке
• отсутствие значения — это отдельное состояние самого объекта, а не nullptr


Поэтому optional удобен, когда функция может вернуть значение или не вернуть ничего:
std::optional<User> find_user(int id);


Но если тебе нужна именно не-владеющая ссылка на уже существующий объект, optional для этого обычно не лучший инструмент.

🔥 std::optional<T> — это контейнер для “значение есть или его нет”, а не просто красивый указатель.

📣 C++ Ready | #совет

Читать полностью…

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

Почему lambda с [=] может работать не так, как ты ожидаешь?

Потому что [=] копирует только локальные переменные из текущей области видимости.
Но если внутри метода класса ты обращаешься к полям объекта, на самом деле захватывается не сам объект целиком, а указатель this.

В таком коде:

cpp id="r8n2fs"
pool.enqueue([=] {
process(data_);
});


может казаться, что data_ безопасно скопирован внутрь lambda. Но это не так.

Фактически lambda использует this, а значит обращается к полю исходного объекта.
Если к моменту выполнения задачи объект уже уничтожен, код получит висячий указатель и undefined behavior.

Из-за этого баг особенно неприятный:
• внешне всё выглядит как “захват по значению”
• код может долго работать нормально
• а потом упасть в асинхронном сценарии, где объект уже не живёт


Если нужен именно снимок данных на момент создания lambda, лучше захватывать его явно:
cpp id="x1kz7d"
auto data = data_;
pool.enqueue([data] {
process(data);
});


А если нужен сам объект, важно явно контролировать его lifetime.

🔥 [=] внутри метода класса не копирует поля объекта автоматически. Чаще всего ты захватываешь this, а не данные.

📣 C++ Ready | #совет

Читать полностью…

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

Безопасное извлечение значения из map: try_emplace вместо лишних проверок!

Когда нужно добавить значение в std::map, если ключа ещё нет, код часто превращается в проверку через find, а потом отдельную вставку. Работает, но получается многословно.

В C++17 для этого есть try_emplace. Он добавляет элемент только если такого ключа ещё нет.

Например:

#include <map>
#include <string>
#include <iostream>

std::map<std::string, int> counters;

counters.try_emplace("errors", 0);


Если ключа "errors" ещё не было, он появится со значением 0.

Если ключ уже есть, значение не будет перезаписано:
counters["errors"] = 5;

counters.try_emplace("errors", 0);

std::cout << counters["errors"] << '\n'; // 5


Это удобно, когда значение дорого создавать или когда важно не затереть уже существующие данные.

try_emplace также возвращает пару: итератор и флаг, была ли вставка выполнена.
auto [it, inserted] = counters.try_emplace("warnings", 0);

if (inserted) {
std::cout << "created\n";
} else {
std::cout << "already exists\n";
}


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

🔥 try_emplace помогает аккуратно добавлять элементы в map: только если ключа ещё нет.

📣 C++ Ready | #практика

Читать полностью…

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

👀 Хочешь понять криптографию не только на уровне терминов, а через код?

Нашёл статью, где автор разбирает два собственных блочных шифра на C++: ESCK-7 и Seal. Это интересный инженерный разбор того, как может быть устроено блочное шифрование.

В статье:

• структура блочного шифра и работа с 64-битными числами
• генерация ключа и преобразования через XOR, NOT и циклические сдвиги
• примеры функций шифрования, расшифровки и изменения ключа

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


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

Читать полностью…

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

📂 Принципы проектирования и архитектуры API!

Например, REST задаёт стандарт взаимодействия по HTTP, GraphQL — гибкую выборку данных, а gRPC — эффективную бинарную коммуникацию.

На схеме — основные области: основы (контракты, HTTP, stateless), паттерны (REST, RPC, WebSockets), безопасность (OAuth2, JWT, TLS), а также дизайн и эволюция API.

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

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

Читать полностью…

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

😎 Нашёл полезную статью на Хабре — отличный пример, как начать писать простую игру на C++ с помощью SFML!

В этой статье:
• Как создать окно SFML и настроить главный цикл с обработкой событий
• Реализация singleton-контроллера для управления движением по клавишам
• Подключение и отображение текстур в игровом цикле

🔊 Советую продолжить читать на Habr!


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

Читать полностью…

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

🧐 Ravesli — подробный курс по C++ с нуля!

Это структурированный обучающий сайт, где собрано более 200 уроков по C++, охватывающих как базовые, так и углублённые темы языка. Отдельное внимание уделено практике: на сайте есть задания, проекты и даже разборы создания игр, что позволяет применять знания в реальных задачах.

📌 Оставляю ссылочку: ravesli.com

📣 C++ Ready | #сайт

Читать полностью…

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

📂 Напоминалка по иерархии памяти и работе storage!

Например, регистры — это самый быстрый уровень памяти внутри CPU, кэш (L1/L2/L3) снижает latency за счёт локальности данных, RAM хранит рабочее состояние приложений, а SSD/HDD используются для персистентного хранения с существенно более высоким временем доступа.

На картинке — базовая иерархия памяти, взаимодействие CPU — cache — RAM — disk, а также упрощённая модель работы HDD и архитектура SSD.

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

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

Читать полностью…

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

🐱 Project-Based Learning — обучение через проекты!

Этот репозиторий собирает лучшие гайды, где вместо теории — реальные проекты, которые можно реализовать с нуля. Внутри есть десятки идей. В разделах по C++ и C# можно найти идеи разного уровня: работа с файлами, сетевое взаимодействие, графика, многопоточность и др. задачи.

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


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

Читать полностью…

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

📂 Напоминалка по HTTP-статусам!

Например, код 200 означает, что всё прошло успешно, а 404 сообщает, что страница не найдена.
Очень полезно держать под рукой, когда работаешь с API или отлаживаешь backend.

На картинке показаны самые часто используемые статусы от 100 до 599.

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

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

Читать полностью…

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

💅 Beautiful — нейросеть для создания презентаций!

Это AI-инструмент для быстрого создания профессиональных презентаций. Достаточно добавить текст и идеи, а нейросеть автоматически подбирает дизайн, выравнивает элементы и формирует слайды. Встроенные умные шаблоны помогают делать презентации аккуратными без ручной настройки — AI сам адаптирует макет при добавлении контента.

📌 Оставляю ссылочку: beautiful.ai

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

Читать полностью…

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

📂 Шпаргалка по вычислительным архитектурам!

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

На картинке — наглядное сравнение архитектуры, модели вычислений и типичных сценариев применения для каждого типа процессоров.

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

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

Читать полностью…

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

😍 PVS-Studio Blog — технические статьи по коду и разработке!

Здесь публикуются подробные разборы ошибок, уязвимостей и практик разработки. Основной фокус на статический анализ кода и реальные кейсы из проектов, включая разборы популярных open-source решений. Блог активно покрывает C++ и C#: публикуются статьи по анализу, поиску багов, особенностям работы компиляторов и практике.

📌 Оставляю ссылочку: pvs-studio.ru

📣 C++ Ready | #сайт

Читать полностью…

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

Почему emplace_back() не всегда лучше push_back()?

Есть популярное заблуждение, что emplace_back() всегда быстрее. Но это не так.

push_back() добавляет в контейнер уже готовый объект.
emplace_back() конструирует объект прямо на месте из переданных аргументов.

Например:

v.emplace_back("world");


здесь строка создается сразу внутри vector, и это действительно удобно.

Но если объект у тебя уже есть:
std::string s = "hello";
v.push_back(s);


то замена на
v.emplace_back(s);


обычно не дает никакого особого выигрыша. По смыслу это почти то же самое.

emplace_back() полезен, когда ты передаешь аргументы конструктора.
push_back() — когда у тебя уже есть готовое значение.

🔥 emplace_back() — не универсально лучший вариант. Используй его там, где нужен именно in-place construction.

📣 C++ Ready | #совет

Читать полностью…
Subscribe to a channel