This media is not supported in your browser
VIEW IN TELEGRAM
Этот репозиторий помогает писать более безопасный, понятный и удобный для поддержки код. Здесь объясняется, как правильно использовать инструменты разработки, оформлять проекты, избегать распространённых ошибок и учитывать производительность, переносимость и многопоточность.
Оставляю ссылочку: GitHub
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍10🔥4
Интересная статья о том, как начать делать игру на C++ с помощью SFML!
В этой статье:
• Как создать базовое окно и подключить SFML к проекту
• Как отрисовать персонажа и подготовить первые игровые объекты
• С чего начинается простая 2D-игра на C++ без тяжёлого движка
📣 C++ Ready | #статья
В этой статье:
• Как создать базовое окно и подключить SFML к проекту
• Как отрисовать персонажа и подготовить первые игровые объекты
• С чего начинается простая 2D-игра на C++ без тяжёлого движка
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥7❤3😁1
Когда в C++ помогает std::exchange?
Иногда нужно забрать старое значение переменной и сразу записать новое. Часто это делают в две строки:
Работает, но намерение размазано, сначала читаем, потом отдельно меняем.
В C++ есть std::exchange:
Он возвращает старое значение, а в переменную кладёт новое.
Это удобно для флагов:
Теперь сразу понятно, мы выключили running и сохранили, был ли он включён раньше.
Ещё пример, забрать накопленный буфер:
Метод возвращает старый buffer, а внутри объекта оставляет пустую строку.
📣 C++ Ready | #совет
Иногда нужно забрать старое значение переменной и сразу записать новое. Часто это делают в две строки:
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, а внутри объекта оставляет пустую строку.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Этот репозиторий представляет собой подробное руководство по современным практикам разработки на C++. В нём собраны рекомендации по организации проектов, стилю кода, оптимизации производительности, тестированию, работе с инструментами анализа и другим аспектам профессиональной разработки.
Оставляю ссылочку: GitHub
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 | #ресурс
Например, std::uniform_int_distribution подходит для случайных целых чисел в диапазоне, а std::normal_distribution для значений с нормальным распределением.
На картинке распределения из <random>: uniform, bernoulli, binomial, geometric, normal, lognormal, poisson, exponential, gamma, weibull и другие варианты с формулами и графиками.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤11🔥5🤝1
Собираем проверку расширений файлов на C++!
Иногда нужно быстро отфильтровать файлы: взять только
Подключим нужные заголовки:
Функция будет принимать путь и расширение:
Обойдём папку рекурсивно:
Проверим расширение:
Теперь можно найти все JSON-файлы:
Если папки нет,
std::filesystem позволяет писать маленькие файловые утилиты без платформенного кода. Такой фильтр легко расширить под поиск логов, конфигов, бэкапов или временных файлов.
📣 C++ Ready | #практика
Иногда нужно быстро отфильтровать файлы: взять только
.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 позволяет писать маленькие файловые утилиты без платформенного кода. Такой фильтр легко расширить под поиск логов, конфигов, бэкапов или временных файлов.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍5🔥2
Разберём std::filesystem: 7 операций для работы с файлами и папками в C++!
std::filesystem помогает писать файловые утилиты без платформенного кода: собирать пути, проверять файлы, создавать папки, обходить директории и аккуратно чистить временные данные. Эта шпора пригодится для CLI-инструментов, логов, конфигов, сборочных скриптов и backend-задач на C++.
📣 C++ Ready | #шпора
std::filesystem помогает писать файловые утилиты без платформенного кода: собирать пути, проверять файлы, создавать папки, обходить директории и аккуратно чистить временные данные. Эта шпора пригодится для CLI-инструментов, логов, конфигов, сборочных скриптов и backend-задач на C++.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤2👍2
Media is too big
VIEW IN TELEGRAM
hacking C++ визуальный сайт с современными материалами по C++!
На сайте собраны гайды, короткие статьи, рецепты, cheat sheets, инфографика и подборки материалов по современному C++: стандартная библиотека, алгоритмы, ranges, контейнеры, templates, move semantics, memory management, random, diagnostics, best practices и инструменты. Это не одна страница и не сухая документация: можно проваливаться в разделы, листать примеры, открывать инфографику и быстро повторять конкретные темы перед практикой или разбором чужого кода.
📣 C++ Ready | #ресурс
На сайте собраны гайды, короткие статьи, рецепты, cheat sheets, инфографика и подборки материалов по современному C++: стандартная библиотека, алгоритмы, ranges, контейнеры, templates, move semantics, memory management, random, diagnostics, best practices и инструменты. Это не одна страница и не сухая документация: можно проваливаться в разделы, листать примеры, открывать инфографику и быстро повторять конкретные темы перед практикой или разбором чужого кода.
Оставляю ссылочку: hackingcpp.com
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4🔥3
Зачем в C++ использовать std::optional?
Иногда функция должна показать, что результат может отсутствовать.
Часто для этого возвращают специальное значение:
Проблема в том, что
Код вызова тоже становится неочевидным:
В C++17 для таких случаев есть
Теперь отсутствие результата выражено прямо в типе:
А само значение можно получить после проверки:
Такой подход хорошо подходит для поиска, парсинга, чтения конфига и любых операций, где “ничего не найдено” нормальный сценарий, а не ошибка программы.
📣 C++ Ready | #совет
Иногда функция должна показать, что результат может отсутствовать.
Часто для этого возвращают специальное значение:
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';
Такой подход хорошо подходит для поиска, парсинга, чтения конфига и любых операций, где “ничего не найдено” нормальный сценарий, а не ошибка программы.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🔥6👍3
Сильная статья о том, как написать свой компилятор на C++ с использованием LLVM!
В этой статье:
• Как компилятор проходит путь от исходного кода до промежуточного представления
• Зачем нужны лексер, парсер, семантика и LLVM IR
• Как устроить ошибки, типы и генерацию кода в собственном языке
📣 C++ Ready | #статья
В этой статье:
• Как компилятор проходит путь от исходного кода до промежуточного представления
• Зачем нужны лексер, парсер, семантика и LLVM IR
• Как устроить ошибки, типы и генерацию кода в собственном языке
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤5🔥4
Когда в C++ лучше использовать std::span?
Иногда функция должна работать с массивом, vector или частью данных, но владеть этими данными ей не нужно.
Часто в таком случае передают vector:
Проблема в том, что функция теперь привязана именно к std::vector.
Если у тебя есть обычный массив, придётся писать перегрузку или создавать vector:
В C++20 для таких случаев есть std::span:
Теперь функция принимает разные источники данных:
Можно передать и часть диапазона:
std::span не владеет памятью. Он просто смотрит на уже существующие данные.
Поэтому нельзя возвращать span на локальный массив:
После выхода из функции массив исчезнет, а span останется висячей ссылкой.
📣 C++ Ready | #совет
Иногда функция должна работать с массивом, 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 останется висячей ссылкой.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤5🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Полезный ресурс для разработчиков на C и C++. На сайте собрана подробная документация по языкам и стандартной библиотеке: типы данных, функции, классы, шаблоны, контейнеры, алгоритмы, работа с памятью, потоки, многопоточность и новые возможности стандартов C++11, C++14, C++17, C++20 и C++23.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍8🔥4
Крутая статья про то, как нарисовать мультяшный взрыв на чистом C++ примерно за 180 строк!
В этой статье:
• Как работает ray marching и численное пересечение луча с объектом
• Как добавить освещение, паттерн, displacement mapping и шум
• Как сохранить результат в PPM и получить готовую картинку без графических библиотек
📣 C++ Ready | #статья
В этой статье:
• Как работает ray marching и численное пересечение луча с объектом
• Как добавить освещение, паттерн, displacement mapping и шум
• Как сохранить результат в PPM и получить готовую картинку без графических библиотек
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍6❤3
Шпаргалка по STL в C++!
Например, vector удобен для быстрого доступа по индексу, set хранит элементы в отсортированном виде, а priority_queue помогает быстро получать максимальный элемент.
На картинке основные контейнеры STL, частые операции, асимптотика, примеры использования sort, binary_search, lower_bound, upper_bound, min_element, max_element, pair, tuple и других полезных инструментов.
Сохрани, чтобы не потерять!
📣 C++ Ready | #ресурс
Например, vector удобен для быстрого доступа по индексу, set хранит элементы в отсортированном виде, а priority_queue помогает быстро получать максимальный элемент.
На картинке основные контейнеры STL, частые операции, асимптотика, примеры использования sort, binary_search, lower_bound, upper_bound, min_element, max_element, pair, tuple и других полезных инструментов.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥4
Собираем небольшой LRU-кэш на C++!
Иногда нужно хранить только последние N значений: результаты дорогих вычислений, ответы локального кэша или недавно использованные настройки. Если лимит превышен, самый старый элемент должен автоматически удаляться.
Для порядка использования удобно взять std::list:
А для быстрого поиска unordered_map:
Добавим лимит:
Когда ключ уже есть, переносим его в начало:
Если ключ новый, просто добавляем его первым:
Теперь проверяем размер кэша:
Соберём это в функцию:
Проверим порядок:
Теперь внутри останутся 4, 1 и 3:
Ожидаемый вывод:
LRU-кэш хорошо показывает, как std::list и unordered_map дополняют друг друга: список хранит порядок, а map даёт быстрый доступ к узлам.
📣 C++ Ready | #практика
Иногда нужно хранить только последние N значений: результаты дорогих вычислений, ответы локального кэша или недавно использованные настройки. Если лимит превышен, самый старый элемент должен автоматически удаляться.
Для порядка использования удобно взять std::list:
std::list<int> order;
А для быстрого поиска unordered_map:
std::unordered_map<int, std::list<int>::iterator> pos;
Добавим лимит:
const std::size_t limit = 3;
Когда ключ уже есть, переносим его в начало:
order.erase(pos[key]);
order.push_front(key);
pos[key] = order.begin();
Если ключ новый, просто добавляем его первым:
order.push_front(key);
pos[key] = order.begin();
Теперь проверяем размер кэша:
if (order.size() > limit) {
pos.erase(order.back());
order.pop_back();
}Соберём это в функцию:
void touch(int key) {
if (pos.contains(key)) {
order.erase(pos[key]);
}
order.push_front(key);
pos[key] = order.begin();
if (order.size() > limit) {
pos.erase(order.back());
order.pop_back();
}
}Проверим порядок:
touch(1);
touch(2);
touch(3);
touch(1);
touch(4);
Теперь внутри останутся 4, 1 и 3:
for (int x : order) {
std::cout << x << ' ';
}Ожидаемый вывод:
4 1 3
LRU-кэш хорошо показывает, как std::list и unordered_map дополняют друг друга: список хранит порядок, а map даёт быстрый доступ к узлам.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤4😁2👍1