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

Автор: @energy_c

РКН: https://clck.ru/3QREHc
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
👎9
Сортируем контейнер через std::ranges::sort!

Допустим, есть вектор чисел, и нужно отсортировать его по возрастанию.
std::vector<int> nums = {4, 1, 7, 3};


Раньше обычно писали так:
std::sort(nums.begin(), nums.end());


Работает, но приходится каждый раз передавать пару итераторов.

В C++20 можно использовать ranges-версию:
std::ranges::sort(nums);


Теперь алгоритм принимает контейнер целиком.

После сортировки получим:
1 3 4 7


Если нужно отсортировать объекты по полю, можно использовать projection:
std::ranges::sort(users, {}, &User::score);


Здесь сортировка идёт не по всему объекту, а по полю score.

Это удобно для рейтингов, таблиц лидеров, списков товаров, отчётов и любых коллекций, где нужно быстро упорядочить данные.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥73
Не копируй элементы в цикле, если их можно читать по ссылке!

В C++ range-based for часто пишут так:
for (auto x : items) {
use(x);
}


Для int или char это нормально.

Но если внутри лежат строки, структуры, объекты или большие классы, каждый элемент будет копироваться.
Например:
for (auto user : users) {
std::cout << user.name << '\n';
}


Если User тяжёлый, такой цикл создаёт лишние копии.

Когда нужно только читать элементы, лучше использовать const auto&:
for (const auto& user : users) {
std::cout << user.name << '\n';
}


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

Если элемент нужно менять тогда используют обычную ссылку:
for (auto& user : users) {
user.active = true;
}


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

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
15👍8🔥5😁2
Почему std::string_view может неожиданно превратиться в висячую ссылку?

std::string_view не хранит собственную строку. Он содержит только ссылку на уже существующие символы.

Поэтому возвращать view на локальный std::string опасно:

std::string_view make_name() {
std::string name = "Ready";
return name;
}


После выхода из функции name уничтожается, а результат указывает в освобождённую память.

Если функция создаёт новую строку, возвращай std::string:

std::string make_name() {
return "Ready";
}


view также может стать недействительным после изменения исходной строки:

std::string text = "C++";
std::string_view view = text;

text += std::string(100, '!');


При расширении text может получить новый буфер, а view останется связан со старым.

Безопасный вариант будет использовать данные с достаточным временем жизни:

constexpr std::string_view channel = "C++ Ready";
std::cout << channel;


Строковый литерал существует до завершения программы, поэтому такой view остаётся корректным.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍64👎1
This media is not supported in your browser
VIEW IN TELEGRAM
💅 Core Guidelines — как писать качественный код на C++!

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

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


📣 C++ Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥159👍6
😒 Официальная библиотека промптов для Claude от Anthropic

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

⚡️Внутри собраны сотни шаблонов под самые разные сценарии:
🟦Для безопасности: готовые конструкции для проверки кода на уязвимости и анализа граничных условий работы алгоритмов.

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

🟦Для автоматизации и менеджмента: промпты под стратегическое планирование, парсинг неструктурированных данных, генерацию технической документации и выстраивание логики для ИИ-агентов.


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

❤️‍🩹Сохраняйте в закладки и внедряйте в свои рабочие процессы.

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

Если вы хотите заложить мощный фундамент начните с нашего бесплатного курса (его прошли уже 1108 человек!).

🟦Разберетесь, как работают кибератаки и как грамотно защитить свои данные.

🟦Познакомитесь с направлениями и профессиями в кибербезопасности, чтобы выбрать свой трек.

🟦Получите скидку, если решите продолжить обучение в CyberYozh Academy.


👉 Начните бесплатно прямо сейчас
🦔 CyberYozh
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥1
Измеряем время выполнения блока кода на C++!

Создадим небольшой RAII-таймер. Он начнёт измерение при создании и автоматически покажет результат при выходе из области видимости.

Сохраним название операции и время запуска:
class ScopeTimer {
std::string name_;
std::chrono::steady_clock::time_point start_;


Добавим конструктор:
public:
explicit ScopeTimer(std::string name)
: name_(std::move(name)),
start_(std::chrono::steady_clock::now()) {}


В деструкторе вычислим прошедшее время:
    ScopeTimer() {
const auto elapsed =
std::chrono::steady_clock::now() - start_;

const auto microseconds =
std::chrono::duration_cast<
std::chrono::microseconds
>(elapsed);


Остаётся вывести результат и закрыть класс:
        std::cout << name_ << ": "
<< microseconds.count()
<< " us\n";
}
};


Теперь измерим сортировку:
{
ScopeTimer timer("sorting");
std::ranges::sort(values);
}


После выхода из блока деструктор вызовется автоматически:
sorting: 1842 us


steady_clock подходит для измерения интервалов, потому что не зависит от перевода системных часов.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥73
Шпаргалка по форматированию вывода в C++!

Например, {:.2f} оставляет два знака после запятой, {:08} дополняет число нулями, а {:x} выводит его в шестнадцатеричном формате.

На картинке синтаксис библиотеки {fmt}: позиционные и именованные аргументы, выравнивание, ширина, точность, системы счисления, строки, указатели, диапазоны и кортежи.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍136🔥6
Почему чтение через map[key] может изменить контейнер?

Обращение через квадратные скобки выглядит как обычное получение значения:
std::cout << hits["api"];


Но если ключа "api" ещё нет, operator[] автоматически создаст его и добавит значение по умолчанию.

Для int таким значением будет 0:
std::map<std::string, int> hits;

std::cout << hits["api"]; // 0
std::cout << hits.size(); // 1


Получается, что код только читал значение, но размер контейнера изменился.

Если нужно найти ключ без вставки, используйте find():
auto it = hits.find("api");

if (it != hits.end()) {
std::cout << it->second;
}


Начиная с C++20 наличие ключа можно проверить через contains():
if (hits.contains("api")) {
std::cout << hits.at("api");
}


at() не создаёт новый элемент. Если ключ отсутствует, метод выбросит std::out_of_range.

При подсчёте событий поведение operator[], наоборот, очень удобно:
++hits["api"];
++hits["api"];

std::cout << hits["api"]; // 2


Используйте map[key], когда автоматическая вставка допустима. Для чтения без изменения контейнера выбирайте find(), contains() или at().

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍74🔥3
Современный C++23 на компьютере с Windows 95!

В этой статье:
• Как получить совместимый 32-битный код современным компилятором
• Зачем объектные файлы передаются старому линкеру Visual C++
• Как заменить недоступные части стандартной библиотеки и работать через WinAPI

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8😁42🔥1
IT мероприятия 🤘

Всё самое интересное для карьеры в IT: митапы, хакатоны, конференции, стажировки и обучение.

Подписывайся 🤘

1. Москва
2. Санкт-Петербург
3. Для стажеров и студентов
Please open Telegram to view this post
VIEW IN TELEGRAM
std::string_view не владеет строкой и в этом легко ошибиться!

std::string_view хранит только указатель на символы и их количество. Он не копирует текст и не продлевает время жизни исходной строки.

Поэтому такой код опасен:
std::string_view name = make_name();


Если make_name() возвращает std::string, временная строка уничтожается в конце выражения. После этого name продолжает указывать на уже недействительную память.

Безопасный вариант сначала сохранить строку:
std::string name = make_name();
std::string_view view = name;


Теперь view можно использовать, пока существует name и операции со строкой не сделали указатель недействительным.

string_view хорошо подходит для параметров функций, которые только читают текст:
void print_name(std::string_view name) {
std::cout << name << '\n';
}


Такой метод принимает строковые литералы, std::string и другие непрерывные последовательности символов без лишнего копирования:
std::string user = "Alex";

print_name(user);
print_name("Admin");


А вот возвращать представление локальной строки нельзя:
std::string_view get_status() {
std::string status = "ready";
return status;
}


После выхода из функции status уничтожается, а возвращённый string_view становится висячим.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥75👍3
Интересная статья о том, как написать виртуальную машину на C++!

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

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥42
Интересный практический проект, собственная игра на C++ для портативной ретроконсоли!

В этой статье:

• Как организовать структуру небольшого игрового проекта
• Как устроить главный игровой цикл и переключение состояний
• Как разделить стартовый экран, игровой процесс и завершение игры
• Как собрать клон Google Dino и запустить его на реальном устройстве

Хороший способ посмотреть, как обычные классы, состояния и игровой цикл превращаются в законченную работающую игру.

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍6🔥3
Как безопасно удалять элементы из контейнера в C++20?

Частая ошибка удалять элементы прямо внутри range-for:
for (int x : values) {
if (x < 0) {
// удалить x?
}
}


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

В C++20 для этого есть std::erase_if:
std::vector<int> values{5, -1, 7, -3};

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


После этого в vector останутся только нужные значения:
// values: 5, 7


То же самое удобно работает и с ассоциативными контейнерами:
std::map<std::string, int> scores{
{"ann", 10},
{"bob", 0},
{"kim", 7}
};

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


Здесь удалятся записи, где значение равно нулю, а код останется коротким и читаемым.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥5👍3
Очень интересная статья о том, как автор пытался воссоздать Minecraft на C++ и Vulkan за одну неделю!

В этой статье:
• Как устроена идея voxel-мира и генерации чанков
• Почему Vulkan требует аккуратной работы с рендерингом и ресурсами
• Как маленький прототип постепенно превращается в собственный игровой движок

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥7👍5
Напоминалка по алгоритмам стандартной библиотеки C++!

Например, std::find_if помогает найти элемент по условию, std::sort сортирует диапазон, а std::transform удобно применять для преобразования значений без ручного цикла.

На картинке шпаргалка по STL-алгоритмам: поиск, сравнение диапазонов, сортировка, partition, rotate, copy, transform, remove, unique и числовые алгоритмы из <numeric>.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥85👍3
Опа, тут бывший сеньор одного из IT-отделов Яндекса Игорь Никитин выкатил целый канал про Python — и это лучшее, что есть в рунете по теме.

Качественные гайды. Советы от известных прогеров. Тематические мемасы. Короче, ничего лишнего.

Хватит душить питона, учись его кодить: https://t.me/+IzIPzvoa7p40ZTUy 🐍
👎6👍1
Собираем маленький scope guard!

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

Писать cleanup руками в каждом return неудобно:
void process() {
enable();

if (!check_input()) {
disable();
return;
}

run_job();
disable();
}


Если return станет больше, легко забыть один из вызовов disable().

Сделаем небольшой scope guard:
#include <functional>
#include <utility>

class ScopeExit {
public:
explicit ScopeExit(std::function<void()> fn)
: fn_(std::move(fn)) {}


В деструкторе он выполнит переданную функцию:
    ~ScopeExit() {
if (fn_) {
fn_();
}
}


Запретим копирование, чтобы cleanup не вызвался дважды:
    ScopeExit(const ScopeExit&) = delete;
ScopeExit& operator=(const ScopeExit&) = delete;


Поля класса:
private:
std::function<void()> fn_;
};


Теперь очистка привязана к области видимости:
void process() {
enable();

ScopeExit guard([] {
disable();
});

if (!check_input()) {
return;
}

run_job();
}


disable вызовется и при обычном завершении, и при раннем return.

Тот же подход удобен для временных файлов:
ScopeExit cleanup([&] {
std::filesystem::remove(path);
});


И для восстановления старого значения:
bool old = config.debug;
config.debug = true;

ScopeExit restore([&] {
config.debug = old;
});


Scope guard это простой способ сделать cleanup надёжным. Код меньше зависит от того, сколько return появится внутри функции.

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