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

Автор: @energy_it

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

Реклама на бирже: https://telega.in/c/cpp_ready
Download Telegram
std::span: безопасная альтернатива T* + size!

Очень часто функции принимают «сырые» данные так:
void process(const int* data, std::size_t size);


Это быстро, но небезопасно:
указатель и размер легко рассинхронизировать;
компилятор никак не помогает;
легко выйти за границы и словить UB.

В C++20 для этого есть std::span — лёгкая обёртка над непрерывным диапазоном памяти. std::span не владеет данными, но всегда знает их размер и тип.

Перепишем сигнатуру функции:
#include <span>

void process(std::span<const int> data) {
for (int x : data) {
// безопасный проход по диапазону
work(x);
}
}


Теперь функция принимает единое целое, а не два разрозненных аргумента.

Вызывать её можно почти так же просто:
#include <vector>
#include <array>

int main() {
std::vector<int> v{1, 2, 3};
std::array<int, 3> a{4, 5, 6};
int raw[] = {7, 8, 9};

process(v); // std::vector
process(a); // std::array
process(raw); // C-массив
}


Никаких кастов, никаких размеров вручную — всё выводится автоматически.

Если же нужно изменять данные, достаточно убрать const:
void normalize(std::span<int> data) {
for (int& x : data) {
x = std::max(x, 0);
}
}


🔥 std::span — это zero-overhead приём: он не копирует данные, не замедляет код и при этом резко снижает шанс UB из-за выхода за границы или перепутанных размеров.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
17👍13🔥9😁1
This media is not supported in your browser
VIEW IN TELEGRAM
☕️ Awesome-Shell — топовая коллекция утилит, скриптов и приёмов для терминала!

Здесь собраны десятки CLI-инструментов, полезные bash/zsh-скрипты, практичные сниппеты и лайфхаки, которые ускоряют работу. Отличный набор для автоматизации, оптимизации и прокачки навыков работы с командной строкой.

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


📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥7👍5
👩‍💻 Строки часто "дешевле", чем вам кажутся!

SSO помогает писать быстрый код без дополнительных усилий — просто используя std::string там, где строки обычно короткие.

В что важно знать:

SSO — это оптимизация реализации, а не контракт стандарта;

Самый большой профит — в большом количестве маленьких строк;

Рост строки может “выключить” SSO, поэтому reserve() часто спасает.


Заключение: Используйте std::string смело, но помните, что SSO — приятный бонус, а не гарантия.

📣 C++ Ready | #гайд
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2513👍7🤝4
📂 Шпаргалка по возможностям C++17

На картинке — краткое напоминание о ключевых нововведениях в C++17: if constexpr, шаблоны с auto, структурные привязки, вложенные пространства имён, атрибуты [[nodiscard]], [[maybe_unused]], [[fallthrough]], сложение параметров с помощью fold-выражений, constexpr-лямбды, прямые инициализации enum.

Полезный сжатый обзор для тех, кто пишет на modern C++ и хочет держать язык под контролем.

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥84
Почему auto иногда делает код более читаемым?

Многие боятся auto, потому что “не видно тип”. Но часто тип как раз мешает чтению: он длинный, шаблонный и не несёт смысла.

Типичный пример — итераторы:
auto it = v.begin();

Вместо:
std::vector<std::string>::iterator it = v.begin();


Смысл строки — “взяли итератор на начало”, а не “прочитай 40 символов типа”.

Ещё один сильный кейс — structured bindings в циклах по map:
for (auto& [key, value] : m) { ... }


Без auto тут обычно появляется std::pair<const std::string, int>&, и читаемость падает.

Где auto особенно уместен:

когда тип очевиден из правой части (v.begin(), make_unique, find, size())
когда тип слишком “шумный” и отвлекает
когда важнее роль переменной, а не её точный тип


А не прятать тип лучше:

когда это влияет на поведение (int vs size_t, auto vs auto&)
когда auto может случайно сделать копию вместо ссылки


🔥 Итог: используй auto, чтобы убрать “шум типов”, но следи за ссылками и const: часто правильнее auto& / const auto&, чем просто auto.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥95
👐 Отличная статья — про оптимизацию через понимание CPU: где теряются такты и почему компилятор не всесилен.

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

• Понять, какие блокировщики оптимизаций мешают компилятору в реальности
• Увидеть, как измерять скорость через CPE и задержки
• Разобраться в приёмах: инварианты, регистры, ветвления, SIMD, циклы

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


📣 C++ Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥64
[[likely]] и [[unlikely]]: когда они реально помогают?

Иногда хочется «подсказать» компилятору, какая ветка выполняется чаще — и получить чуть больше производительности без переписывания логики.

Для этого в C++ есть атрибуты [[likely]] и [[unlikely]]: они помечают ветку как более/менее вероятную, чтобы компилятор мог лучше разложить код (например, под предсказание ветвлений).

Пример: быстрый путь — когда всё ок, редкий — когда ошибка:
int parse_number(std::string_view s) {
if (s.empty()) [[unlikely]] {
return -1; // редкая ошибка
}

// основной “горячий” путь
return static_cast<int>(s[0] - '0');
}


Или наоборот: редкая проверка на ошибку в начале функции:
int divide(int a, int b) {
if (b == 0) [[unlikely]] {
return 0; // обработка ошибки
}

return a / b; // обычный случай
}


Но важно: эти атрибуты — не «магия оптимизации». Они полезны, когда:
у тебя реально есть горячий код (часто вызываемый участок);
есть ветка, которая почти никогда не выполняется (ошибка, исключительный случай);
профилирование или здравый смысл подтверждают, что распределение сильно перекошено.


Хороший паттерн: помечать [[unlikely]] на проверках ошибок, а основной путь оставлять без атрибутов (или ставить [[likely]] на него, если хочется подчеркнуть намерение):
int handle(int fd) {
if (fd < 0) [[unlikely]] {
return -1;
}

// нормальный случай
return do_work(fd);
}


🔥 [[likely]] / [[unlikely]] — это тонкая настройка: используй их точечно на редких ошибках и исключительных ветках. Если нет горячего участка — лучше не шуметь и оставить оптимизацию компилятору.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍117
This media is not supported in your browser
VIEW IN TELEGRAM
☕️ Смотрите что нашел — Explainshell.

Вводишь любую команду в терминале, и он по частям объясняет, что делает каждая часть. Не просто man-ка, а понятный синтакс-анализ.

Особенно кайф для тех, кто работает в Linux/DevOps/CI среде и хочет разбираться, а не наугад копипастить из StackOverflow.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍9🤝81
9👍4🔥4
Что же выведет консоль?
Anonymous Quiz
34%
A
51%
B
11%
C
4%
D
11👍5🔥3
👩‍💻 Шпаргалка по Bash!

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

Сохрани, чтобы терминал перестал казаться магией и начал работать на тебя

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍7🔥4
RAII против goto cleanup: убираем утечки и ручную зачистку!

В “почти C”-коде на C++ часто открываешь ресурс, потом ещё один, а при ошибке нужно не забыть всё закрыть. Обычно это превращается в goto cleanup или дублирование free/fclose перед каждым return.

Вот как это выглядит в начале: уже приходится помнить, что закрывать при неудаче:
FILE* f = std::fopen("data.txt", "r");
if (!f) return -1;

char* buf = (char*)std::malloc(1024);
if (!buf) { std::fclose(f); return -1; }


Дальше появляется “ошибка в середине”, и чтобы не дублировать очистку, добавляют cleanup:
int rc = 0;

if (something_bad()) {
rc = -1;
goto cleanup;
}


А в конце — ручной порядок освобождения, который легко сломать правками:
cleanup:
std::free(buf);
std::fclose(f);
return rc;


В C++ это решает RAII: ресурс заворачиваем в объект, и он освобождается автоматически при выходе из области видимости.

Файл можно обернуть в std::unique_ptr с deleter’ом:
using FilePtr = std::unique_ptr<FILE, decltype(&std::fclose)>;

FilePtr f(std::fopen("data.txt", "r"), &std::fclose);
if (!f) return -1;


Буфер тоже делаем RAII-шным — и теперь любой ранний return безопасен:
auto buf = std::make_unique<char[]>(1024);

if (something_bad()) return -1;
return 0;


🔥 RAII убирает goto cleanup и ручные освобождения: добавляешь новые ветки и выходы — и не думаешь, где что закрыть.

📣 C++ Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
14👍7🔥6
This media is not supported in your browser
VIEW IN TELEGRAM
❤️ Scrimba — интерактивное обучение программированию!

Если обычные видеоуроки не заходят и хочется больше практики — Scrimba решает эту задачу. Здесь обучение построено так, что ты не просто смотришь объяснение, а сразу работаешь с кодом прямо в уроке: меняешь примеры, запускаешь и смотришь результат. На платформе есть множество языков и технологий.

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍139🔥7
std::move не перемещает, а “разрешает перемещать”!

Частая ошибка — думать, что std::move(x) сам переносит ресурсы и “обнуляет” объект.

На самом деле std::move — это просто приведение к rvalue-ссылке: он говорит компилятору “считай, что этот объект можно перемещать”.

Реальное перемещение происходит только там, где вызывается:
• move-конструктор
• move-оператор присваивания
или перегрузка функции, принимающая rvalue (T&&)

Поэтому строка:
auto b = std::move(a);

не “переместила” ничего магически — она просто создала b (а вот *каким образом* — копированием или перемещением — зависит от типа и контекста).

Перемещение гарантированно случается, когда ты строишь/присваиваешь объект из rvalue:
std::string c = std::move(b); // move-конструктор


Важный практический вывод: после std::move(x) объект x остаётся валидным, но его состояние не определено (его можно переиспользовать только через присваивание или безопасные операции типа clear()/empty()/size() — в зависимости от типа).

🔥 Итог: ставь std::move там, где ты вроде бы “отдаёшь” объект (в контейнер, в return, в конструктор/присваивание) — это не перенос, а явный сигнал: “дальше мне это значение не нужно”.

📣 C++ Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍75
This media is not supported in your browser
VIEW IN TELEGRAM
😎 CodeAbbey — тренажёр алгоритмического мышления!

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

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

📣 C++ Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
15👍8🔥8😁1
🎄 Всех с наступающим новым 2025 2026 годом!

Поставлю себе цель: набрать более 25 тысяч подписчиков. Желаю каждому выполнить планы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31🔥118😁2