en
Feedback

Don't get caught by a cheater! Telemetrio finds and tags such channels 👉 If you want to see the tag, subscribe

C++ geek

C++ geek

Open in Telegram

Учим C/C++ на примерах

Show more
3 504
Subscribers
No data24 hours
-27 days
-2630 days
Posts Archive
Пару фишек про шаблоны, которые могут спасти час дебага: 1. CTAD (Class Template Argument Deduction, C++17) Не надо вручную указывать аргументы:

   std::pair p(42, 3.14); // вместо std::pair<int, double> p(42, 3.14);
   std::vector v = {1,2,3}; // компилятор сам выведет std::vector<int>
   
Помогает сократить код и избежать опечаток. 2. Fold-выражения (C++17) для арг-паков:

   auto sum = [](auto... args){
       return (args + ...);  // ((a + b) + c) + ...
   };
   std::cout << sum(1,2,3,4); // 10
   
Позволяют писать операции над любым числом параметров без рекурсии. 3. SFINAE → Concepts (C++20) Старый стиль через enable_if легко сломать:

   template<class T>
   std::enable_if_t<std::is_integral_v<T>, T>
   foo(T x) { return x*2; }
   
С Concepts чище и понятнее:

   template<std::integral T>
   T foo(T x) { return x*2; }
   
4. CRTP (Static polymorphism) Быстрее виртуалок и без RTTI:

   template<class D>
   struct Base {
       void interface() { static_cast<D*>(this)->impl(); }
   };
   struct Derived : Base<Derived> {
       void impl() { std::cout<<"OK\n"; }
   };
   
Шаблоны — это не только про универсальность, но и про ясность кода. Освой тонкости, и они станут 🔧, а не головняком. ➡️ @cpp_geek

Тонкости STL, которые часто вылетают в продакшн: 1. Инвалидирование итераторов При vector::erase все итераторы от позиции удаления до end() становятся «битые». Чтобы безопасно отфильтровать и удалить элементы, пользуйтесь erase–remove идиомой:

   auto it = std::remove_if(v.begin(), v.end(), [](int x){ return x < 0; });
   v.erase(it, v.end());
   
remove_if сдвигает «хвост» вперёд, но не меняет размер контейнера. 2. reserve vs resize * v.reserve(n) выделяет память, но не создаёт объектов → size() не меняется, можно безопасно push_back. * v.resize(n) создаёт n элементов, инициализированных значениями по умолчанию. 3. Производительность std::distance На random-access итераторах (например, vector) это O(1), а на bidirectional или forward (например, list) — O(n). Для списков используйте size() (C++11+) или считайте вручную в критичных местах. 4. emplace_back vs push_back При сложных типах emplace_back может избежать лишнего копирования:

   v.emplace_back(ctor_arg1, ctor_arg2);
   // vs
   v.push_back(MyType(ctor_arg1, ctor_arg2));
   
5. Памятка про компараторы В set или map ваш компаратор должен задавать строгий-уровень-менее (operator<): если comp(a,b)==true, то comp(b,a) обязан быть false. Иначе — UB. Быстро, без воды, но с пользой — проверяйте эти моменты в своём коде! ➡️ @cpp_geek

🚀 Анонимные функции (лямбды) в C++ Лямбды — это удобные анонимные функции, которые можно объявлять прямо в коде. Вот ключевые фишки: 🔹 Базовый синтаксис

auto lambda = [] { /* тело функции */ };
Каждая лямбда имеет уникальный тип, даже если выглядит так же, как другая. 🔹Захват переменных - По значению [x] — создаётся копия. - По ссылке [&x] — работаем с оригиналом.

int a = 10, b = 10;
auto fn = [a, &b] {
a++; // Не влияет на оригинал
b++; // Меняет исходную переменную
};
🔹 Параметры и возвращаемое значение

auto sum = [](int x, int y) -> int { return x + y; };
Можно опустить -> int, если компилятор сам выведет тип. 🔹 Изменяемые лямбды (mutable) Если захватываем по значению и хотим менять значение между вызовами:

int count = 0;
auto bump = [count]() mutable { ++count; };
🔹Обобщённые лямбды (C++14+) Можно использовать auto для параметров:

auto sum = [](auto x, auto y) { return x + y; };
🔹Условная компиляция (if constexpr) Позволяет обрабатывать разные типы по-разному:

auto print = [](auto x) {
if constexpr (std::is_same_v) {
std::cout << «int: " << x;
}
};
💡 Вывод: Лямбды делают код лаконичнее, поддерживают захват переменных, обобщённые вычисления и даже constexpr-логику. Отлично заменяют мелкие функции и функторы. ➡️ @cpp_geek

✅ Чек-лист: Линейные структуры данных в C++ Линейные структуры данных — фундамент программирования на C++. Правильный выбор с
✅ Чек-лист: Линейные структуры данных в C++ Линейные структуры данных — фундамент программирования на C++. Правильный выбор структуры может значительно повысить эффективность вашего кода. 🎯 Векторы (std::vector) ✓ Используйте reserve() для предварительного выделения памяти, когда примерно известен размер ✓ Применяйте push_back() для добавления элементов и pop_back() для удаления с конца ✓ Доступ по индексу выполняется за O(1) с помощью оператора [] ✓ Используйте at() вместо [] для проверки границ массива 🎯 Списки (std::list) ✓ Отдавайте предпочтение при частых вставках/удалениях в середине ✓ Используйте splice() для эффективного перемещения элементов между списками ✓ Помните, что прямой доступ по индексу невозможен — только итерация ✓ Двунаправленные итераторы позволяют двигаться как вперед, так и назад 🎯 Очереди и стеки (std::queue, std::stack) ✓ Стек (LIFO): используйте push() для добавления и pop() для извлечения ✓ Очередь (FIFO): применяйте push() для добавления и pop() для извлечения ✓ Функция front() позволяет посмотреть первый элемент без удаления ✓ Обе структуры являются адаптерами и построены на других контейнерах 🎯 Массивы (std::array) ✓ Используйте для данных фиксированного размера, известного на этапе компиляции ✓ Более эффективны чем векторы для неизменяемых данных ✓ Поддерживают STL-алгоритмы (sort, find и др.) ✓ Проверяйте границы с функцией at() во избежание ошибок доступа ➡️ @cpp_geek

🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.ru/i_odmin Все для системного администратора https://max.ru/bash_srv Bash Советы https://max.ru/sysadminof Книги для админов, полезные материалы https://max.ru/i_odmin_book Библиотека Системного Администратора https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др. https://max.ru/tipsysdmin Типичный Сисадмин Excel лайфхак 📌 https://t.me/Excel_lifehack Excel лайфхак Английский с нуля 🇬🇧 https://max.ru/UchuEnglish 1C разработка 📌 https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С Программирование C++📌 https://max.ru/cpp_lib Библиотека C/C++ разработчика Программирование Go📌 https://max.ru/golang_lib Библиотека Go (Golang) разработчика Программирование React📌 https://max.ru/react_lib React Программирование Python 📌 https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчика Java разработка 📌 https://max.ru/bookjava Библиотека Java разработчика GitHub Сообщество 📌 https://max.ru/githublib Интересное из GitHub Базы данных (Data Base) 📌 https://max.ru/database_info Все про базы данных Фронтенд разработка 📌 https://max.ru/frontend_1 Подборки для frontend разработчиков Библиотеки 📌 https://max.ru/programmist_of Книги по программированию https://max.ru/proglb Библиотека программиста https://max.ru/bfbook Книги для программистов Программирование 📌 https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻 Шутки программистов 📌 https://max.ru/itumor Шутки программистов Защита, взлом, безопасность 📌 https://max.ru/thehaking Канал о кибербезопасности https://max.ru/xakkep_1 Хакер Free Книги, статьи для дизайнеров 📌 https://max.ru/odesigners Статьи, книги для дизайнеров Математика 📌 https://max.ru/Pomatematike Канал по математике https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике Вакансии 📌 https://max.ru/progjob Вакансии в IT Мир технологий 📌 https://max.ru/mir_teh Канал для любознательных Бонус 📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга https://max.ru/mockva_life Свежие новости Москвы https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП

How to: убираем типы с помощью std::decay_t std::decay_t — один из самых полезных type traits в C++. Он имитирует процесс пер
How to: убираем типы с помощью std::decay_t std::decay_t — один из самых полезных type traits в C++. Он имитирует процесс передачи параметра по значению, «разрушая» исходный тип. 🔄 Что именно делает decay_t? • Убирает cv-квалификаторы • Превращает ссылки в соответствующие типы без ссылок • Преобразует массивы в указатели • Преобразует функции в указатели на функции 💻 Пример:

#include <type_traits>
#include <iostream>

int main() {
    // const int& -> int
    static_assert(std::is_same_v<std::decay_t<const int&>, int>);
    
    // int[10] -> int*
    static_assert(std::is_same_v<std::decay_t<int[10]>, int*>);
    
    // void(int) -> void(*)(int)
    static_assert(std::is_same_v<std::decay_t<void(int)>, void(*)(int)>);
    
    std::cout << "All assertions passed!" << std::endl;
}
🚀 Где это используется? • В шаблонном программировании для упрощения работы с типами • В std::make_shared и std::make_unique для определения типа создаваемого объекта • При написании обобщенного кода, где нужна правильная дедукция типов 🔍 И да, название «decay» («разрушение») действительно отражает суть — тип «разрушается» до базового представления! ➡️ @cpp_geek

std::move ничего не двигает 🤯 Вот типичная ошибка, которая встречается даже у опытных: std::string foo() { std::string s = "
std::move ничего не двигает 🤯 Вот типичная ошибка, которая встречается даже у опытных:

std::string foo() {
    std::string s = "hello";
    return std::move(s); // ❌
}
Кажется, что std::move здесь «ускоряет» возврат. Но это зло. На самом деле, компилятор и без std::move применяет Return Value Optimization (RVO) и возвращает s без копирования. А вот std::move ломает RVO — теперь вызывается перемещающий конструктор, и компилятор не может это оптимизировать. Результат: * return s; — возможно, вообще без затрат (RVO). * return std::move(s); — гарантированно перемещение (дороже, чем RVO). 🔑 Правило: никогда не пиши std::move при возврате локальной переменной по значению. Доверься компилятору. Когда std::move действительно нужен? Например:

void bar(std::string&& s) {
    auto local = std::move(s); // перемещаем из rvalue-ссылки
}
Здесь всё логично: мы явно говорим, что хотим «украсть» содержимое. Вывод: std::move — это не перемещение, а обещание, что объект можно обобрать. А перемещать будет уже компилятор. ➡️ @cpp_geek

C++: зачем [[nodiscard]] на bool — и почему это важно Когда функция возвращает bool, часто возникает соблазн проигнорировать результат:

is_valid(user); // ничего не делает!
А теперь представьте, что is_valid() проверяет критическое условие. Без проверки — баг, возможно даже security-уязвимость. Чтобы защититься от такого, с C++17 есть [[nodiscard]]:

[[nodiscard]] bool is_valid(const User& user);
Теперь, если результат проигнорировать — компилятор предупредит:
warning: ignoring return value of 'is_valid', declared with attribute 'nodiscard'
Можно ещё улучшить читаемость — использовать [[nodiscard("Must check if user is valid")]], чтобы компилятор написал пояснение в варнинге (начиная с C++20). 🔥 Лайфхак: ставьте [[nodiscard]] на все функции, где игнорирование результата — это почти всегда ошибка. Особенно на: * проверки (is_...) * операции с возможным фейлом (try_..., parse_...) * RAII-объекты с флагами состояния Не ленитесь — [[nodiscard]] спасает от тонких багов и делает код надёжнее. ➡️ @cpp_geek

📌 Сегодня расскажу вам о проблеме, которую часто упускают: небезопасный доступ к std::vector по указателю после push_back. Смотрим код:

std::vector<MyStruct> vec;
vec.reserve(10); // вроде как "гарантируем", что ничего не сломается

MyStruct* ptr = &vec[0];
vec.push_back(MyStruct{});

// BOOM! ptr теперь может быть невалиден
💥 Даже несмотря на reserve(10), контейнер имеет право перераспределить память при любом push_back, если по каким-то причинам решил, что нужно. Например, при нарушении alignment или внутренней оптимизации. 🔒 Что делать безопасно: * Никогда не храните указатели или ссылки на элементы std::vector, если планируете его изменять. * Если нужно, используйте индекс:

size_t index = 0;
vec.push_back(...);
use(vec[index]);
* Или используйте std::list / std::deque, если вам действительно нужны устойчивые указатели. 🧠 Это классический источник UB (Undefined Behavior), особенно в старых проектах, где кто-то “оптимизировал” память, сохранив указатель. Поделитесь, попадались ли вам такие баги? 👇 ➡️ @cpp_geek

Сегодня хочу показать вам один из приёмов, который часто выручает в реальной разработке на C++ — оборачивание C API в безопасные RAII-объекты. Многие библиотеки на C (например, OpenSSL, SQLite, libpng) требуют вручную управлять ресурсами — открывать, закрывать, аллоцировать и освобождать. Это источник ошибок: забыли free(), упустили close(), получили утечку памяти или файлового дескриптора. В C++ мы можем обернуть такие ресурсы в класс с аккуратным деструктором:

class FileHandle {
public:
    explicit FileHandle(FILE* file) : file_(file) {}
    ~FileHandle() {
        if (file_) {
            fclose(file_);
        }
    }

    FILE* get() const { return file_; }

private:
    FILE* file_;
};
Теперь, даже если функция выбросит исключение или произойдет выход из области видимости, файл закроется автоматически! Такие классы легко комбинировать с std::unique_ptr через кастомные делетеры для ещё большей безопасности. Не забывайте: RAII (Resource Acquisition Is Initialization) — один из важнейших паттернов для профессионального C++. ➡️ @cpp_geek

🔥 Сегодня я расскажу про одно коварное поведение std::vector, которое часто становится причиной багов и утечек. 📌 Проблема: Удаление элементов в цикле Многие делают так:

std::vector<int> v = {1, 2, 3, 4, 5};

for (size_t i = 0; i < v.size(); ++i) {
    if (v[i] % 2 == 0) {
        v.erase(v.begin() + i);
    }
}
Но это ошибка! После erase вектор сдвигает все элементы, и индекс i указывает уже не на тот элемент. В результате часть значений пропускается. ✅ Правильный способ — использовать итераторы:

auto it = v.begin();
while (it != v.end()) {
    if (*it % 2 == 0)
        it = v.erase(it);
    else
        ++it;
}
Так вы не теряете элементы и не получаете неопределённое поведение. 🧠 Советы: - Всегда помните, что erase инвалидирует итераторы и индексы. - Если хотите удалять по условию — лучше использовать std::remove_if + erase.

v.erase(std::remove_if(v.begin(), v.end(), [](int x) {
    return x % 2 == 0;
}), v.end());
➡️ @cpp_geek

Сегодня покажу вам полезную вещь, которую часто упускают даже опытные C++ разработчики - Альтернативные способы инициализации std::vector. 🔹 std::vector: Инициализация — больше, чем просто {} Многие используют векторы так:

std::vector<int> v = {1, 2, 3};
Но есть и другие варианты, которые помогут сделать код выразительнее, а в некоторых случаях — эффективнее. 🔸 1. Инициализация с количеством элементов и значением

std::vector<int> v(5, 10); // 5 элементов по 10
🔥 Часто полезно, когда нужен предзаполненный буфер. 🔸 2. С использованием std::fill

std::vector<int> v(10);
std::fill(v.begin(), v.end(), 7);
✅ Удобно, когда вектор уже создан, но нужно всё заполнить определённым значением. 🔸 3. std::generate и std::iota

std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1); // 1, 2, 3, ..., 10
🚀 Идеально подходит, когда нужно создать диапазон значений. 🔸 4. Из другой коллекции (через итераторы)

std::list<int> lst = {4, 5, 6};
std::vector<int> v(lst.begin(), lst.end());
🔄 Позволяет гибко конвертировать контейнеры. 🔸 5. Через reserve + emplace_back

std::vector<std::pair<int, int>> v;
v.reserve(3);
v.emplace_back(1, 2);
v.emplace_back(3, 4);
v.emplace_back(5, 6);
🔧 Отлично, когда важна производительность и хочется избежать лишнего копирования. ✅ Совет: Не забывайте про reserve, если знаете итоговый размер вектора — избежите лишних реаллокаций. Надеюсь, вы узнали что-то новое. Поделитесь, какие приёмы чаще используете вы? ➡️ @cpp_geek

👨‍💻 Сегодня покажу вам удобный способ, как избавиться от болей с #include в больших C++ проектах. Когда проект растёт, количество инклудов становится пугающим. Компиляция тормозит, зависимости запутаны, порядок подключения начинает влиять на поведение программы… Знакомо? 📌 Решение — Precompiled Headers (PCH). Это не магия, а вполне рабочая практика. Всё просто: 1. Создаём файл pch.h, в котором собираем самые часто используемые инклюды:

   // pch.h
   #pragma once
   #include <iostream>
   #include <vector>
   #include <map>
   // и т.д.
   
2. Добавляем его в компиляцию с флагом:

   g++ -x c++-header pch.h -o pch.h.gch
   
3. Теперь любой другой файл, который первым инклудит pch.h, компилируется быстрее. ⚡️ Бонус: современные сборочные системы, вроде CMake, умеют работать с PCH почти автоматически. Достаточно:

target_precompile_headers(my_target PRIVATE pch.h)
🧠 Маленький совет: следите, чтобы в pch.h не попадали редко используемые или изменяющиеся файлы — иначе получите обратный эффект. Пользовались ли вы PCH в своих проектах? Какой прирост производительности заметили? ➡️ @cpp_geek

🚀 Сегодня я покажу вам простой, но очень полезный приём в C++: как элегантно управлять временем жизни ресурса с помощью std::unique_ptr и кастомного deleter'а. 📌 Задача: у нас есть не-C++ ресурс, например, FILE* из stdio.h. Мы хотим, чтобы он автоматически закрывался, как только выходит из области видимости. Вместо ручного вызова fclose, используем std::unique_ptr с кастомным deleter'ом:

#include <memory>
#include <cstdio>

int main() {
    // Кастомный deleter для FILE*
    auto fileDeleter = [](FILE* f) {
        if (f) {
            std::puts("Файл закрывается автоматически!");
            std::fclose(f);
        }
    };

    // Умный указатель с кастомным deleter'ом
    std::unique_ptr<FILE, decltype(fileDeleter)> file(std::fopen("data.txt", "r"), fileDeleter);

    if (!file) {
        std::perror("Не удалось открыть файл");
        return 1;
    }

    // Файл будет автоматически закрыт в конце блока main()
}
💡 Такой подход безопаснее, чем fopen/fclose, особенно в реальных проектах с множеством return'ов и исключениями. А главное — код остаётся чистым и идиоматичным. 🔥 А вы используете unique_ptr с кастомным deleter’ом в своём коде? Поделитесь, для чего вы его применяли! ➡️ @cpp_geek

🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.ru/i_odmin Все для системного администратора https://max.ru/bash_srv Bash Советы https://max.ru/sysadminof Книги для админов, полезные материалы https://max.ru/i_odmin_book Библиотека Системного Администратора https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др. https://max.ru/tipsysdmin Типичный Сисадмин Excel лайфхак 📌 https://t.me/Excel_lifehack Excel лайфхак 1C разработка 📌 https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С Программирование C++📌 https://max.ru/cpp_lib Библиотека C/C++ разработчика Программирование Go📌 https://max.ru/golang_lib Библиотека Go (Golang) разработчика Программирование React📌 https://max.ru/react_lib React Программирование Python 📌 https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчика Java разработка 📌 https://max.ru/bookjava Библиотека Java разработчика GitHub Сообщество 📌 https://max.ru/githublib Интересное из GitHub Базы данных (Data Base) 📌 https://max.ru/database_info Все про базы данных Фронтенд разработка 📌 https://max.ru/frontend_1 Подборки для frontend разработчиков Библиотеки 📌 https://max.ru/programmist_of Книги по программированию https://max.ru/proglb Библиотека программиста https://max.ru/bfbook Книги для программистов Программирование 📌 https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻 Шутки программистов 📌 https://max.ru/itumor Шутки программистов Защита, взлом, безопасность 📌 https://max.ru/thehaking Канал о кибербезопасности https://max.ru/xakkep_1 Хакер Free Книги, статьи для дизайнеров 📌 https://max.ru/odesigners Статьи, книги для дизайнеров Математика 📌 https://max.ru/Pomatematike Канал по математике https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике Вакансии 📌 https://max.ru/progjob Вакансии в IT Мир технологий 📌 https://max.ru/mir_teh Канал для любознательных Бонус 📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга https://max.ru/mockva_life Свежие новости Москвы https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП

🔧 Что делать, если std::sort тормозит? Привет! Сегодня хочу поделиться с вами одной типичной ситуацией, с которой сталкивался не раз — сортировка больших контейнеров через std::sort, которая неожиданно начинает тормозить. Вызываешь вроде обычную сортировку, а работает медленно. Почему так? 🔍 Проблема — не std::sort, а компаратор! В 90% случаев проблема не в std::sort, а в лямбде или компараторе, который вы передаёте. Особенно если он: 1. Вызывает копирование: вы сравниваете по значениям, а не по ссылке. 2. Делает что-то тяжёлое внутри: например, вызывает метод, делает std::string копию, обращается к БД (да, и такое видел!). 3. Некеширует результат: например, каждый раз считает длину строки. ✅ Как ускорить сортировку: - Передавайте данные по ссылке, особенно если у вас вектор структур:

  std::sort(vec.begin(), vec.end(), [](const MyStruct& a, const MyStruct& b) {
      return a.key < b.key;
  });
  
- Если у вас есть вычисление ключа — используйте схему "decorate-sort-undecorate":

  std::vector<std::pair<int, size_t>> temp;
  for (size_t i = 0; i < vec.size(); ++i)
      temp.emplace_back(compute_key(vec[i]), i);

  std::sort(temp.begin(), temp.end());
  std::vector<MyStruct> result;
  for (const auto& [_, i] : temp)
      result.push_back(vec[i]);
  
🧠 Мораль: Если std::sort "медленный", не спешите винить алгоритм. Лучше проверьте, что вы передаёте ему на вход. ➡️ @cpp_geek

🔥 Ловим баги в C++ на лету с помощью AddressSanitizer (ASan) Если valgrind — это медленный, но подробный детектив, то ASan — это охрана, которая ловит баги прямо во время исполнения. Быстро, точно, удобно. 💡 Что такое ASan? Это часть компилятора (clang или gcc), которая вставляет дополнительные проверки в бинарник. Работает во время запуска, ловит: - выход за границы массива, - use-after-free, - double free, - утечки памяти (с флагом LeakSanitizer). 👨‍💻 Пример:

// asan_example.cpp
#include <iostream>

int main() {
    int* arr = new int[5];
    arr[10] = 42; // выход за границу
    delete[] arr;
    return 0;
}
⚙️ Компиляция с ASan:

g++ -fsanitize=address -g asan_example.cpp -o app
🚀 Запуск:

./app
📄 Результат:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000050
READ of size 4 at 0x602000000050 thread T0
    #0 0x... in main asan_example.cpp:6
📌 Плюсы ASan: - Мгновенная обратная связь; - Прост в использовании; - Отлично работает с CI (GitHub Actions, GitLab CI и т.д.); - Поддерживает LeakSanitizer (-fsanitize=leak). 📉 Минусы: - Увеличивает размер бинарника; - Иногда мешает оптимизациям; - Не ловит всё (например, утечки в сторонних lib без debug info). 🔧 Совет: Запускай тесты с -fsanitize=address в debug-сборках. Это бесплатно и спасает от кучи головной боли в будущем. 🧵 Используешь ли ты ASan в своих проектах? Или только valgrind? Пиши в комментах👇 ➡️ @cpp_geek

🔧 Как ловить утечки памяти в C++ за 5 минут Инструмент — valgrind. Когда пишем на C++, особенно без smart pointers, утечки памяти — обычное дело. Часто их даже не видно. А valgrind — это наш рентген. 👣 Быстрый гайд: 1. Установи valgrind:

   sudo apt install valgrind
   
2. Собери проект с отладочной информацией:

   g++ -g main.cpp -o app
   
3. Запусти под valgrind:

   valgrind ./app
   
4. И читай отчёт:
   ==12345== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
   
💡 Фишка: Добавь --leak-check=full и --track-origins=yes — получишь больше деталей, где именно утечка:

valgrind --leak-check=full --track-origins=yes ./app
➡️ @cpp_geek

🎯 Как избежать макросов в C++ и остаться довольным Сегодня я покажу вам, как можно избавиться от макросов в C++ и заменить и
🎯 Как избежать макросов в C++ и остаться довольным Сегодня я покажу вам, как можно избавиться от макросов в C++ и заменить их на более безопасные и выразительные конструкции. 🔴 Проблема: #define — это зло. Они не уважают область видимости, не отлаживаются нормально, не подчиняются типам и могут вызвать кучу проблем, особенно в больших проектах. 👉 Вместо #define PI 3.14 Используем:

constexpr double PI = 3.14;
👉 Вместо #define SQUARE(x) ((x)*(x)) Используем шаблон:

template<typename T>
constexpr T square(T x) {
    return x * x;
}
👉 Вместо #ifdef DEBUG ... #endif Используем:

#ifdef DEBUG
inline constexpr bool is_debug = true;
#else
inline constexpr bool is_debug = false;
#endif
А дальше просто:

if constexpr (is_debug) {
    std::cout << "Debug mode\n";
}
💡 constexpr, inline, template и if constexpr — это ваш новый арсенал для выразительного и безопасного кода без макросов. ➡️ @cpp_geek

🧵 RAII — главный секрет устойчивого к утечкам C++ кода Привет! Сегодня хочу напомнить о технике, без которой невозможно писа
🧵 RAII — главный секрет устойчивого к утечкам C++ кода Привет! Сегодня хочу напомнить о технике, без которой невозможно писать безопасный и устойчивый C++ код — это RAII (Resource Acquisition Is Initialization). RAII — это идиома, в которой захват ресурса (файл, сокет, память, мьютекс) происходит в конструкторе объекта, а освобождение — в деструкторе. Благодаря этому ресурсы освобождаются автоматически, даже при исключениях. Пример:

#include <fstream>

void saveData(const std::string& filename) {
    std::ofstream file(filename); // открытие файла
    if (!file.is_open())
        throw std::runtime_error("Cannot open file");

    file << "some data"; // файл закроется автоматически
}
RAII делает твой код: ✅ Безопасным к утечкам ✅ Устойчивым к исключениям ✅ Лёгким для чтения и сопровождения 💡 Совет: всегда оборачивай "ручные" ресурсы в обёртки — std::unique_ptr, std::lock_guard, std::ofstream, std::thread и т.д. ➡️ @cpp_geek