ar
Feedback
C++ geek

C++ geek

الذهاب إلى القناة على Telegram

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

إظهار المزيد
3 541
المشتركون
-424 ساعات
-147 أيام
-2930 أيام
أرشيف المشاركات
🔥 Ловим баги в 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

Как отслужить срочку, работая с Геранями, и получить диплом по дуальной системе Алабуга Политех?

Как упростить дебаг через std::format и std::source_location Когда вы отлаживаете сложный баг, бывает сложно быстро понять, г
Как упростить дебаг через std::format и std::source_location Когда вы отлаживаете сложный баг, бывает сложно быстро понять, где и почему произошла ошибка. С C++20 стало гораздо проще автоматизировать логирование и сделать его по-настоящему информативным. Вот пример:

#include <iostream>
#include <format>
#include <source_location>

void log(const std::string& message,
         const std::source_location location = std::source_location::current())
{
    std::cout << std::format("[{}:{} - {}] {}\n",
                             location.file_name(),
                             location.line(),
                             location.function_name(),
                             message);
}

int divide(int a, int b)
{
    if (b == 0) {
        log("Попытка деления на ноль");
        return 0;
    }
    return a / b;
}
📌 Этот код выведет:
[main.cpp:16 - divide] Попытка деления на ноль
Вы больше не пишете руками __FILE__, __LINE__ и __func__. Всё это делает std::source_location. А с std::format — красиво и читаемо. ➡️ @cpp_geek

📌 Как эффективно работать с std::unordered_map? Всем привет! Сегодня расскажу о том, как правильно работать с std::unordered_map, чтобы избежать неожиданных проблем с производительностью. 🔥 Почему std::unordered_map? std::unordered_map — это хеш-таблица в C++, обеспечивающая быстрый доступ к данным (O(1) в среднем). В отличие от std::map, который построен на красно-черном дереве (O(log N) доступ), unordered_map работает быстрее при больших объемах данных. ⚠️ Подводные камни и советы по оптимизации 1️⃣ Выбор хорошей хеш-функции Стандартные хеш-функции (`std::hash`) работают хорошо для примитивных типов, но если вы работаете со сложными структурами (например, std::pair или std::string), лучше использовать специализированные хешеры.

struct MyHash {
    std::size_t operator()(const std::pair<int, int>& p) const {
        return std::hash<int>()(p.first) ^ (std::hash<int>()(p.second) << 1);
    }
};
Использование ^ (xor) и сдвигов помогает уменьшить коллизии. 2️⃣ Избегайте частых рехеширований При вставке элементов хеш-таблица может перераспределять память (rehash), что затратно. Лучше заранее задать нужный размер:

std::unordered_map<int, std::string> myMap;
myMap.reserve(10000);  // Уменьшаем количество рехеширований
Это особенно полезно, если вы примерно знаете, сколько элементов будет в контейнере. 3️⃣ Оптимизация использования памяти Если ваш unordered_map хранит тяжелые структуры, можно использовать std::reference_wrapper или хранить данные по shared_ptr:

std::unordered_map<int, std::shared_ptr<MyStruct>> myMap;
Так вы избежите лишнего копирования. 4️⃣ Правильное использование find Перед operator[] всегда проверяйте, есть ли элемент в контейнере. Так вы избежите ненужных вставок:

if (myMap.find(key) != myMap.end()) {
    // Обрабатываем существующий ключ
}
Или используйте try_emplace, чтобы избежать двойного вычисления ключа:

myMap.try_emplace(key, "значение по умолчанию");
📌 Вывод: std::unordered_map — мощный инструмент, но при неправильном использовании может работать неэффективно. Выбирайте хорошие хеш-функции, контролируйте рехеширование и оптимизируйте память. ➡️ @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 Типичный Сисадмин 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 Свежие новости Москвы

std::span — мощная альтернатива std::vector и std::array Сегодня поговорим о std::span — контейнере, который делает работу с массивами и векторами в C++ более удобной и эффективной. 🚀 ❌ Проблема: Лишние копии данных Представьте, что у нас есть функция, принимающая массив чисел:

void processArray(const std::vector<int>& arr) {
    for (int num : arr) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}
С одной стороны, передача const std::vector<int>& предотвращает копирование, но что, если у нас массив std::array или сырой int[]? Придётся перегружать функцию или копировать данные в std::vector. ✅ Решение: Используем std::span std::span позволяет передавать любой диапазон (`std::vector`, std::array, сырые массивы) без копирования:

#include <iostream>
#include <span>
#include <vector>
#include <array>

void processArray(std::span<int> arr) {
    for (int num : arr) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::array<int, 5> arr = {6, 7, 8, 9, 10};
    int rawArr[] = {11, 12, 13, 14, 15};

    processArray(vec);      // ✅ Работает
    processArray(arr);      // ✅ Работает
    processArray(rawArr);   // ✅ Работает
}
🚀 Преимущества std::spanНе копирует данные — передаётся как ссылка ✅ Работает с любыми последовательностямиГибкость — можно создавать срезы без копий Пример использования .subspan(), чтобы передавать часть массива:

std::vector<int> vec = {1, 2, 3, 4, 5};
std::span<int> sp = vec;
processArray(sp.subspan(2)); // Выведет: 3 4 5
⚠️ Важно - std::span не владеет данными. Убедитесь, что исходные данные живут дольше span. - Не поддерживает автоматическое изменение размера, как std::vector. 📌 Итог Если ваша функция принимает std::vector<int>&, std::array<int, N>&, int[] или даже std::initializer_list<int>, замените их на std::span<int>! Это сделает код более гибким и эффективным. 🔥 ➡️ @cpp_geek

📌 Оптимизация работы со строками в C++: std::string_view vs std::string Привет, друзья! Сегодня хочу обсудить одну из самых частых проблем в C++ – работу со строками. А именно, почему std::string_view – это мощный инструмент, который может значительно ускорить ваш код. ❌ Проблема: Копирование строк Допустим, у вас есть функция, которая принимает строку:

void process(std::string s) {
    // работа со строкой
}
Каждый раз, когда вызывается эта функция, создаётся новая копия строки. Если строка длинная, это дорого по времени и памяти. ✅ Решение: Используем std::string_view С std::string_view можно избежать лишнего копирования:

void process(std::string_view s) {
    // работа со строкой без копирования
}
Теперь s – это просто представление строки, а не её копия. Вы можете передавать как std::string, так и char*, что делает API более гибким. 🚀 Преимущества std::string_view: ✔ Не создает копий – работает быстрее. ✔ Поддерживает стандартные операции (substr, find и т. д.). ✔ Работает с std::string, char*, массивами символов. ✔ Идеально подходит для парсинга и работы с текстом. 🔥 Важно помнить: - std::string_view не управляет памятью, так что будьте осторожны с временными строками. - Если строка-источник уничтожена, std::string_view станет невалидным. Пример неверного использования:

std::string_view bad() {
    std::string s = "Hello";
    return s; // ⚠ UB, строка уничтожена!
}
➡️ @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 Типичный Сисадмин 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 Свежие новости Москвы

🚀 Оптимизация циклов в C++: маленькие хитрости для больших скоростей Сегодня поговорим об оптимизации циклов в C++. Даже если ваш код работает, это не значит, что он работает быстро. Давайте разберём несколько трюков, которые помогут выжать максимум из циклов. 🔥 1. Избегайте ненужных вычислений внутри цикла ❌ Плохо:

for (int i = 0; i < vec.size(); i++) {  
    process(vec[i]);  
}
Хорошо:

size_t size = vec.size();
for (size_t i = 0; i < size; i++) {  
    process(vec[i]);  
}
Почему? vec.size() может вызываться при каждой итерации, что может замедлить выполнение, особенно если это не std::vector, а другой контейнер. ⚡ 2. Используйте reserve() для вектора Если вы заранее знаете, сколько элементов добавите в std::vector, вызовите reserve(). Это сократит количество реаллокаций памяти.

std::vector<int> vec;
vec.reserve(1000); // резервируем место для 1000 элементов
for (int i = 0; i < 1000; i++) {
    vec.push_back(i);
}
🏎️ 3. Предпочитайте range-based for Классический цикл for:

for (size_t i = 0; i < vec.size(); i++) {  
    process(vec[i]);  
}
Современный range-based for:

for (const auto& elem : vec) {  
    process(elem);  
}
Плюсы: ✅ Улучшает читаемость ✅ Избегает ненужных индексаций ✅ Позволяет компилятору оптимизировать код 🔄 4. std::transform вместо for Если вы преобразуете данные из одного контейнера в другой, используйте std::transform:

std::vector<int> src = {1, 2, 3, 4, 5};
std::vector<int> dst(src.size());

std::transform(src.begin(), src.end(), dst.begin(), [](int x) { return x * 2; });
Зачем? ✔️ Работает быстрее за счёт оптимизаций ✔️ Код становится короче и читабельнее 🎯 Вывод Оптимизация циклов — это не магия, а грамотное использование возможностей C++. Убирайте лишние вычисления, используйте reserve(), применяйте range-based for и std::transform, и ваш код станет быстрее и элегантнее. Используете ли вы std::transform в своём коде? Делитесь в комментариях! 👇 ➡️ @cpp_geek

Какие есть особенности статических полей класса в языке С++? Статические поля класса в C++ имеют несколько особенностей: 1. Общий доступ: статические поля являются общими для всех объектов этого класса. Это означает, что изменение значения статического поля в одном объекте, изменяет его для всех объектов этого класса. 2. Инициализация: статические поля инициализируются только один раз, когда программа запускается. Значения статических полей сохраняются на протяжении всего времени работы программы. 3. Доступ: доступ к статическим полям класса возможен без создания объекта этого класса, например, используя имя класса и оператор :: . 4. Память: статические поля класса хранятся не в куче или стеке, а в статической области памяти, что позволяет им занимать память только один раз, независимо от количества созданных объектов класса. ➡️ @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 Типичный Сисадмин 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 Свежие новости Москвы

📌 Оптимизация кода с std::optional в C++ Привет, друзья! Сегодня поговорим про std::optional — мощный инструмент, который делает код чище и безопаснее. 💡 Зачем нужен std::optional? Обычно, если функция не может вернуть корректное значение, приходится использовать: ✔ Возвращаемое значение с ошибочным кодом (неудобно, особенно если 0 или -1 могут быть валидными). ✔ Выброс исключения (дорого по ресурсам). ✔ Указатели (nullptr, но требует дополнительных проверок). 🔥 Альтернатива? Используем std::optional!

#include <iostream>
#include <optional>
#include <string>

std::optional<std::string> findUser(int id) {
    if (id == 42) return "John Doe";
    return std::nullopt;
}

int main() {
    auto user = findUser(42);
    
    if (user) {
        std::cout << "User found: " << *user << std::endl;
    } else {
        std::cout << "User not found!" << std::endl;
    }
}
✅ Код стал чище: нет лишних проверок nullptr, исключений или специальных значений. 🎯 Когда использовать? 🔹 Когда функция может вернуть "ничего", но исключения и специальные значения не подходят. 🔹 Для более понятного API (например, парсинг строки в число). 🔹 Когда важно избежать неопределенного состояния (например, с переменной внутри класса). А ты уже используешь std::optional в своем коде? Делись опытом в комментариях! ⬇🔍 ➡️ @cpp_geek

Бинарный поиск Чаще всего бинарный поиск (бинпоиск) используют, чтобы найти элемент в отсортированном массиве. Мы начинаем ис
Бинарный поиск Чаще всего бинарный поиск (бинпоиск) используют, чтобы найти элемент в отсортированном массиве. Мы начинаем искать с середины массива. Если находим то, что нужно, или если больше нечего рассматривать, мы останавливаемся. В противном случае мы решаем, в каком направлении — вправо или влево от середины — мы должны продолжить поиск. Так как пространство поиска после каждой проверки делится на два, то время выполнения алгоритма — O(log n). Код выводит следующее: бинарный поиск: нашли по индексу 4 Если искомый элемент не найден, но мы хотим найти ближайший элемент меньше или больше запроса, то можно использовать функции STL lower_bound() и upper_bound(). ➡️ @cpp_geek

Напишите базовую реализацию std::shared_ptr std::shared_ptr — умный указатель, который позволяет разделять владение объектом
Напишите базовую реализацию std::shared_ptr std::shared_ptr — умный указатель, который позволяет разделять владение объектом между несколькими shared_ptr. Когда последний shared_ptr уничтожается, он автоматически удаляет объект. ➡️ @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 и др. 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 Свежие новости Москвы

♻️ Идеальное преступление: Как создать утечку памяти с помощью умных указателей? С появлением std::shared_ptr в C++ многие выдохнули: "Наконец-то счетчик ссылок всё сделает за нас, больше никаких утечек!". Но умные указатели не обладают интеллектом. И их очень легко обмануть. Самая частая причина «фантомных» утечек памяти в современном C++ это Циклическая зависимость (Circular Dependency). 🪤 Ловушка: Змея, кусающая себя за хвост Представьте игру. У нас есть Игрок (Player) и Гильдия (Guild). • Игрок должен знать, в какой Гильдии он состоит. • Гильдия должна знать, кто её лидер (Игрок). Вы пишете такой код:

struct Player; // Предварительное объявление

struct Guild {
    std::shared_ptr<Player> leader;
    ~Guild() { std::cout << "Guild deleted\n"; }
};

struct Player {
    std::shared_ptr<Guild> myGuild;
    ~Player() { std::cout << "Player deleted\n"; }
};

void Play() {
    auto p = std::make_shared<Player>(); // ref_count(Player) = 1
    auto g = std::make_shared<Guild>();  // ref_count(Guild) = 1
    
    p->myGuild = g; // ref_count(Guild) = 2
    g->leader = p;  // ref_count(Player) = 2
} 
// Конец функции. Локальные p и g уничтожаются.
// ref_count(Player) падает до 1.
// ref_count(Guild) падает до 1.
Итог: Функция завершилась. Объекты больше никому в программе не нужны. Но их деструкторы никогда не вызовутся. Они держат друг друга в заложниках, потому что счетчик не упал до нуля. Вы потеряли память. ⚔️ Спаситель: std::weak_ptr std::weak_ptr - это умный указатель-наблюдатель. Он умеет смотреть на объект, которым владеет shared_ptr, но не увеличивает его счетчик ссылок. Чтобы разорвать цикл, мы должны определить, кто кем владеет (кто важнее), а кто просто ссылается. Допустим, Гильдия существует независимо от лидера, поэтому она будет просто "наблюдать" за ним. ✅ Правильный код:

struct Guild {
    // Слабая ссылка! Не влияет на время жизни Player.
    std::weak_ptr<Player> leader; 
};
Теперь при выходе из функции счетчик Player спокойно упадет до нуля. Player удалится. Его деструктор удалит shared_ptr на Гильдию. Счетчик Гильдии упадет до нуля, и она тоже удалится. Чистая победа! 👀 Как пользоваться weak_ptr? Так как weak_ptr не гарантирует, что объект еще жив (ведь он его не держит), из него нельзя просто так прочитать данные. Вы обязаны превратить его в shared_ptr с помощью метода .lock().

// Если Игрок еще жив, lock() вернет валидный shared_ptr.
// Если Игрок удален, lock() вернет nullptr.
if (std::shared_ptr<Player> ptr = g->leader.lock()) {
    std::cout << "Лидер на месте: " << ptr->name;
} else {
    std::cout << "Лидер покинул нас...";
}
💡 Золотое архитектурное правило: Стройте связи в виде дерева. Сверху вниз - владение (shared_ptr или unique_ptr). Снизу вверх - наблюдение (weak_ptr или обычный *, если время жизни жестко гарантировано). Никогда не делайте цикл из shared_ptr. #cpp #memory #smartpointers #leaks #oop #coding #tips ➡️ @cpp_geek

🧬 Двойная цена std::shared_ptr: Почему профи всегда пишут make_shared? Мы все используем умные указатели. Но то, как вы их создаете, кардинально меняет работу с памятью под капотом. Встречали такой код?

// 🐢 ПЛОХО: Классический подход
std::shared_ptr<User> user(new User());
Кажется, всё логично: выделили память через new, передали в shared_ptr. Но на деле вы заставляете программу сделать две аллокации (выделения памяти) вместо одной. ⚙️ Анатомия shared_ptr std::shared_ptr состоит из двух частей: 1. Сам объект (ваши данные User). 2. Контрольный блок (Control Block) - служебная структура, где лежат счетчики ссылок (reference count) и счетчики weak_ptr. Когда вы пишете std::shared_ptr<User>(new User()), происходит следующее: 1. Отрабатывает new User() - программа идет к ОС и просит кусок памяти. 2. Конструктор shared_ptr видит сырой указатель, понимает, что ему нужен Контрольный блок, и еще раз идет к ОС за вторым куском памяти. Два системных вызова. Фрагментация кучи (heap). Промахи кэша процессора, потому что объект и счетчик лежат в разных концах памяти. 🚀 Решение: std::make_shared

// 🚀 ХОРОШО: Единый блок памяти
auto user = std::make_shared<User>();
Что делает make_shared? Он считает размер вашего объекта User + размер Контрольного блока, и просит у операционной системы один большой кусок памяти за один раз. Плюсы:В 2 раза меньше аллокаций. Код работает быстрее. • Cache Locality. Объект и счетчик ссылок лежат в памяти впритык друг к другу. Процессор это обожает. • Безопасность. До C++17 старый подход с new мог привести к утечке памяти, если функция принимала несколько аргументов и один из них бросал исключение. С make_shared это исключено. 🦇 Темная сторона (О чем не пишут в туториалах) Есть ровно один случай, когда make_shared может навредить. Это связано со слабыми указателями (std::weak_ptr). Если вы удалили все shared_ptr, вызывается деструктор объекта User. Но если остался хотя бы один weak_ptr, Контрольный блок обязан жить! А так как make_shared склеил Контрольный блок и объект в один кусок памяти, оперативная память из-под объекта User не вернется системе, пока жив weak_ptr (даже если сам объект уже "мертв" и деструктор отработал). Если ваш объект весит 500 Мегабайт - вы получите «фантомную» утечку памяти. 💡В 99% случаев используйте std::make_shared. Используйте new std::shared_ptr только если у вас гигантские объекты, на которые подолгу смотрят «зависшие» weak_ptr, или если вам нужен кастомный удалитель (custom deleter). #cpp #memory #pointers #optimization #sharedptr #coding #tips ➡️ @cpp_geek