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

Автор: @energy_it

РКН: https://clck.ru/3QREHc

Реклама на бирже: https://telega.in/c/cpp_ready
Download Telegram
📂 Принципы проектирования и архитектуры API!

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

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

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍12🔥5
Почему 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥5👍4
👀 Хочешь понять криптографию не только на уровне терминов, а через код?

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

В статье:

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

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍4🔥3
Безопасное извлечение значения из 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 | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥145👍3
📂 Напоминалка для работы с OOP Design Patterns!

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

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

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥64
Почему 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥7👍4
📂 Напоминалка по памяти и накопителям!

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

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

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
19👍6🔥6
Почему 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 | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍4🔥3
This media is not supported in your browser
VIEW IN TELEGRAM
☕️ Code․mu Tasker — бесплатный практический задачник по плюсам!

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

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
14🔥6👍4
This media is not supported in your browser
VIEW IN TELEGRAM
❤️ Free Programming Books — огромная коллекция бесплатных книг по программированию!

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

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


📣 C++ Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
👍147🤝6
Удаление элементов без 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 | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥53
📂 Напоминалка по масштабированию базы данных!

Например, Indexing ускоряет поиск по таблицам, а Sharding помогает разделить большие объёмы данных между несколькими узлами.

На картинке — 7 стратегий масштабирования БД: индексы, materialized views, denormalization, vertical scaling, caching, replication и sharding.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥65🤝1
👩‍💻 Рассмотрим std::tie - удобный способ распаковывать значения и сравнивать объекты!

С его помощью можно связывать переменные в tuple из ссылок, пропускать ненужные значения через std::ignore и компактно сравнивать несколько полей сразу.

📣 C++ Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥185👍3👎1🤝1
💡 Автор показывает, как на чистом C++ собрать минимальный трассировщик лучей и получить первый рендер без тяжёлых движков!

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


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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
17👍7🤝3
Почему std::move внутри forwarding-функции может быть ошибкой?

Потому что T&& в шаблоне — это не всегда rvalue-ссылка.
В таком контексте это forwarding reference, которая может принять и временный объект, и обычную lvalue-переменную.

Например:
std::string s = "hello";

wrapper(s);


Здесь в wrapper передается lvalue.
Но внутри функции мы пишем:
process(std::move(value));


И этим насильно превращаем value в rvalue.

В итоге process() может переместить данные из объекта s, хотя вызывающий код передавал обычную переменную и не ожидал, что из нее что-то “заберут”.

То есть проблема не в самом std::move, а в том, что он всегда делает аргумент кандидатом на перемещение.

Для perfect forwarding нужно использовать:
template <class T>
void wrapper(T&& value) {
process(std::forward<T>(value));
}


std::forward<T> сохраняет исходную категорию значения:
lvalue остается lvalue
rvalue остается rvalue

А std::move всегда говорит: “можно перемещать”.

🔥 В forwarding-коде std::move часто слишком агрессивен. Если хочешь сохранить поведение аргумента — используй std::forward<T>.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍54
📂 Паттерны многопоточности, которые стоит знать!

Многопоточность — это не запуск нескольких thread. В реальных системах приходится управлять shared state, очередями задач, producer/consumer-потоками, read/write доступом и координацией выполнения.

На картинке — популярные multithreading patterns: read-write lock, thread pool, producer-consumer, future/promise и другие подходы, которые помогают организовать concurrent-код.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
13🔥7🤝5
Быстро удаляем пробелы в начале и в конце строки!

Когда мы читаем строки из файла, пользовательского ввода или сетевого запроса — часто получаем "шум": пробелы, табы, переводы строк.

Во многих языках есть встроенные trim()-функции, но в C++ стандартной такой нет. Зато её легко реализовать самому — компактно, эффективно и без сторонних зависимостей.

Начнём с подключения нужных заголовков:
#include <string>
#include <cctype> // std::isspace
#include <algorithm>
#include <iostream>


Теперь реализуем функцию trim, которая:
• пропускает все пробелы с начала строки;
• пропускает все пробелы с конца;
• возвращает обрезанную часть как новую строку:
std::string trim(const std::string& s) {
auto start = std::find_if_not(s.begin(), s.end(), ::isspace);
auto end = std::find_if_not(s.rbegin(), s.rend(), ::isspace).base();
return (start < end) ? std::string(start, end) : "";
}


Проверим, как это работает на примере строки с лишними пробелами и переводами строк:
std::string raw = "   \t\n Hello, world! \n ";
std::string cleaned = trim(raw);

std::cout << "[" << cleaned << "]\n";


Результат выполнения:
[Hello, world!]


🔥 Теперь у тебя есть удобная функция, которая безопасно удаляет "мусор" по краям строки.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥98👍4