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

Автор: @energy_c

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

Реклама на бирже: https://telega.in/c/cpp_ready
Download Telegram
Собираем маленький 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
6👍4🔥3
Интересная статья о том, как устроить свою SDL-подобную библиотеку на C++!

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

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
9🔥5👍3
Шпаргалка по special member functions в C++!

Например, если в классе объявить деструктор, компилятор уже не будет автоматически объявлять move constructor и move assignment. А если объявить move constructor, copy-операции могут стать deleted.

На картинке таблица правил генерации специальных методов класса: default constructor, destructor, copy constructor, copy assignment, move constructor и move assignment в зависимости от того, что уже объявил разработчик.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥115👍5
Собираем типобезопасные флаги через enum class!

Иногда нужно хранить набор прав или режимов: чтение, запись, выполнение, логирование, debug-режимы. Часто для этого используют обычные int-флаги, но с ними легко случайно смешать разные значения.

Начнём с enum class:
enum class Permission : unsigned {
Read = 1 << 0,
Write = 1 << 1,
Exec = 1 << 2
};


Сам по себе enum class не умеет складываться через |, поэтому добавим оператор:
Permission operator|(Permission a, Permission b) {
return static_cast<Permission>(
static_cast<unsigned>(a) | static_cast<unsigned>(b)
);
}


Теперь можно собрать набор прав:
auto user = Permission::Read | Permission::Write;


Чтобы проверять наличие флага, сделаем маленькую функцию:
bool has(Permission value, Permission flag) {
return (
static_cast<unsigned>(value) &
static_cast<unsigned>(flag)
) != 0;
}


Использование получается читаемым:
if (has(user, Permission::Write)) {
std::cout << "Можно изменять данные\n";
}


Можно добавить и удаление флага:
Permission remove(Permission value, Permission flag) {
return static_cast<Permission>(
static_cast<unsigned>(value) & ~static_cast<unsigned>(flag)
);
}


Например, забрать право записи:
user = remove(user, Permission::Write);


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

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍7🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
👍 C++ Best Practices — практические правила разработки на C++!

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

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

📣 C++ Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍10🔥4
Интересная статья о том, как начать делать игру на C++ с помощью SFML!

В этой статье:
• Как создать базовое окно и подключить SFML к проекту
• Как отрисовать персонажа и подготовить первые игровые объекты
• С чего начинается простая 2D-игра на C++ без тяжёлого движка

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥73😁1
Когда в C++ помогает std::exchange?

Иногда нужно забрать старое значение переменной и сразу записать новое. Часто это делают в две строки:
auto old = state;
state = State::Closed;


Работает, но намерение размазано, сначала читаем, потом отдельно меняем.

В C++ есть std::exchange:
auto old = std::exchange(state, State::Closed);


Он возвращает старое значение, а в переменную кладёт новое.

Это удобно для флагов:
bool wasRunning = std::exchange(running, false);


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

Ещё пример, забрать накопленный буфер:
std::string takeBuffer() {
return std::exchange(buffer, {});
}


Метод возвращает старый buffer, а внутри объекта оставляет пустую строку.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
👨‍💻 CppBestPractices — рекомендации по написанию кода!

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

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

📣 C++ Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍8🔥5
Шпаргалка по random distributions в C++!

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

На картинке распределения из <random>: uniform, bernoulli, binomial, geometric, normal, lognormal, poisson, exponential, gamma, weibull и другие варианты с формулами и графиками.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1311🔥5🤝1
Собираем проверку расширений файлов на C++!

Иногда нужно быстро отфильтровать файлы: взять только .log, .json, .txt или изображения. Сделаем небольшую функцию на std::filesystem, которая проходит по папке и возвращает файлы с нужным расширением.

Подключим нужные заголовки:
#include <filesystem>
#include <string>
#include <vector>

namespace fs = std::filesystem;


Функция будет принимать путь и расширение:
std::vector<fs::path> find_files(
const fs::path& root,
std::string_view extension
) {
std::vector<fs::path> result;


Обойдём папку рекурсивно:
    for (const auto& entry : fs::recursive_directory_iterator(root)) {
if (!entry.is_regular_file()) {
continue;
}


Проверим расширение:
        if (entry.path().extension() == extension) {
result.push_back(entry.path());
}
}

return result;
}


Теперь можно найти все JSON-файлы:
auto files = find_files("configs", ".json");

for (const auto& file : files) {
std::cout << file << '\n';
}


Если папки нет, recursive_directory_iterator может бросить исключение. Для утилит это нормально обработать явно:
try {
auto files = find_files("configs", ".json");
} catch (const fs::filesystem_error& error) {
std::cerr << error.what() << '\n';
}


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

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍5🔥2
Разберём std::filesystem: 7 операций для работы с файлами и папками в C++!

std::filesystem помогает писать файловые утилиты без платформенного кода: собирать пути, проверять файлы, создавать папки, обходить директории и аккуратно чистить временные данные. Эта шпора пригодится для CLI-инструментов, логов, конфигов, сборочных скриптов и backend-задач на C++.

📣 C++ Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥122👍2
Media is too big
VIEW IN TELEGRAM
hacking C++ визуальный сайт с современными материалами по C++!

На сайте собраны гайды, короткие статьи, рецепты, cheat sheets, инфографика и подборки материалов по современному C++: стандартная библиотека, алгоритмы, ranges, контейнеры, templates, move semantics, memory management, random, diagnostics, best practices и инструменты. Это не одна страница и не сухая документация: можно проваливаться в разделы, листать примеры, открывать инфографику и быстро повторять конкретные темы перед практикой или разбором чужого кода.

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


📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍4🔥3
Зачем в C++ использовать std::optional?

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

Часто для этого возвращают специальное значение:
int find_user_id(std::string_view name) {
if (name.empty()) {
return -1;
}

return 42;
}


Проблема в том, что -1 это договорённость, которую легко забыть.

Код вызова тоже становится неочевидным:
int id = find_user_id(name);

if (id == -1) {
std::cout << "not found\n";
}


В C++17 для таких случаев есть std::optional:
std::optional<int> find_user_id(std::string_view name) {
if (name.empty()) {
return std::nullopt;
}

return 42;
}


Теперь отсутствие результата выражено прямо в типе:
auto id = find_user_id(name);

if (!id) {
std::cout << "not found\n";
return;
}


А само значение можно получить после проверки:
std::cout << *id << '\n';


Такой подход хорошо подходит для поиска, парсинга, чтения конфига и любых операций, где “ничего не найдено” нормальный сценарий, а не ошибка программы.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
9🔥6👍3
Сильная статья о том, как написать свой компилятор на C++ с использованием LLVM!

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

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍75🔥4
Когда в C++ лучше использовать std::span?

Иногда функция должна работать с массивом, vector или частью данных, но владеть этими данными ей не нужно.

Часто в таком случае передают vector:
int sum(const std::vector<int>& values) {
int result = 0;

for (int value : values) {
result += value;
}

return result;
}


Проблема в том, что функция теперь привязана именно к std::vector.

Если у тебя есть обычный массив, придётся писать перегрузку или создавать vector:
int data[] = {1, 2, 3};

// sum(data) не подойдёт


В C++20 для таких случаев есть std::span:
int sum(std::span<const int> values) {
int result = 0;

for (int value : values) {
result += value;
}

return result;
}


Теперь функция принимает разные источники данных:
std::vector<int> a{1, 2, 3};
std::array<int, 3> b{4, 5, 6};
int c[] = {7, 8, 9};

sum(a);
sum(b);
sum(c);


Можно передать и часть диапазона:
sum(std::span(a).subspan(1, 2));


std::span не владеет памятью. Он просто смотрит на уже существующие данные.

Поэтому нельзя возвращать span на локальный массив:
std::span<int> bad() {
int values[] = {1, 2, 3};
return values;
}


После выхода из функции массив исчезнет, а span останется висячей ссылкой.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍155🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
👨‍💻 cppreference — информативный справочник по C и C++!

Полезный ресурс для разработчиков на C и C++. На сайте собрана подробная документация по языкам и стандартной библиотеке: типы данных, функции, классы, шаблоны, контейнеры, алгоритмы, работа с памятью, потоки, многопоточность и новые возможности стандартов C++11, C++14, C++17, C++20 и C++23.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍8🔥4