ch
Feedback
C++ geek

C++ geek

前往频道在 Telegram

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

显示更多
3 613
订阅者
无数据24 小时
-17
-3630
帖子存档
🏗 Что на самом деле происходит, когда std::vector «лопается»? Мы все любим push_back. Это удобно: кидаешь данные в вектор, а он сам разбирается с памятью. Но что происходит, когда вы добавляете элемент, а capacity (вместимость) вектора закончилась? Происходит Реаллокация (Reallocation). И это гораздо дороже, чем кажется. ⚙️ Алгоритм катастрофы: 1. Поиск новой земли: Вектор понимает, что места нет. Он обращается к оперативной памяти и просит выделить новый блок памяти. Обычно он в 1.5 или 2 раза больше текущего. 2. Великое переселение: Все элементы из старого блока памяти копируются (или перемещаются, если есть noexcept move-конструктор) в новый блок. ⚫️Если у вас там 1,000,000 тяжелых объектов - удачи процессору. 😅 3. Уничтожение: Для всех объектов в старом блоке вызываются деструкторы. 4. Снос: Старый блок памяти возвращается системе. 🚨 Почему это проблема? 1. Удар по производительности: Обычно push_back работает за O(1) (мгновенно). Но в момент реаллокации сложность подскакивает до O(N). Это создает непредсказуемые лаги (latency spikes). В системах реального времени (gamedev, high-load) это недопустимо. 2. Инвалидация итераторов и ссылок (ОПАСНО): Это источник багов №1.

std::vector<int> vec = {1, 2, 3};
int& ref = vec[0]; // Ссылка на первый элемент

// ... добавляем много элементов ...
for(int i=0; i < 100; ++i) vec.push_back(i);

// 💥 Вектор переехал в новую память. 
// Старая память удалена. ref теперь указывает в мусор.
std::cout << ref; // Undefined Behavior (Crash)

🛡 Как лечить? Если вы хотя бы примерно знаете, сколько элементов будет в векторе, всегда используйте reserve().

std::vector<User> users;
users.reserve(1000); // Сразу выделяем память

// Теперь первые 1000 push_back будут дешевыми
// и не вызовут реаллокации.

💡 Итог: std::vector это отличный инструмент, но за его «магию» расширения платит процессор. Помогайте ему через reserve(). #cpp #stdvector #performance #memory #coding #tips ➡️ @cpp_geek

✂️ C++17: Перестаньте копировать строки! (std::string_view) Мы привыкли передавать строки в функции по константной ссылке: const std::string&. Нам кажется, что это эффективно, ведь мы не копируем объект, верно? Не всегда. 🛑 Если вы передаете в такую функцию обычный текст в кавычках (строковый литерал) или часть другой строки, C++ втайне от вас создаст временный объект std::string, выделит память в куче (heap allocation), скопирует туда данные и только потом передаст ссылку. Решение? std::string_view. 👀 Что это такое? std::string_view - это супер-легкий объект, который ничего не хранит сам. Он просто «смотрит» на существующую строку. Внутри него только указатель на начало текста и длина. Никаких аллокаций. Никаких копий. Ноль оверхеда. 🆚 Сравним:

// 🐢 ПЛОХО (до C++17)
void Log(const std::string& msg) { /* ... */ }

// При вызове создается временный std::string!
Log("Critical Error"); 


// 🚀 ХОРОШО (C++17)
void Log(std::string_view msg) { /* ... */ }

// Никаких аллокаций. Просто передаем указатель и длину.
Log("Critical Error"); 

🔥 Суперсила: Substrings без боли Самое вкусное начинается, когда нужно взять подстроку. ⚫️std::string::substr() - создает новую строку (копирование + аллокация). ⚫️std::string_view::substr() - просто сдвигает указатель и меняет размер (математическая операция за наносекунды). ⚠️ Осторожно! (Подводный камень) Так как string_view не владеет данными, а только смотрит на них, вы должны быть уверены, что исходная строка живет дольше, чем string_view. ⚫️ ✅ Использовать как аргумент функции. ⚫️ ❌ Возвращать из функции, если исходная строка была локальной переменной. 💡 Итог: Если вам нужно только «почитать» строку (в аргументах функции), почти всегда используйте std::string_view вместо const std::string&. #cpp #cpp17 #optimization #stringview #coding #tips ➡️ @cpp_geek

🚀 Микро-оптимизация в C++20: Early Return + Атрибуты вероятности В прошлом посте мы разобрали, как Early Return (ранний возврат) спасает нас от вложенных if и делает код чище. Но в C++20 мы можем сделать этот код еще и потенциально быстрее! Встречайте атрибуты [[likely]] и [[unlikely]]. 🧠 В чем суть? Современные процессоры пытаются предсказать, какую ветку кода программа выполнит следующей (Branch Prediction). Если процессор угадал - всё летает. Если ошибся - теряем такты на очистку конвейера. С помощью атрибутов мы даем компилятору (и процессору) «инсайд»: какая ветка будет выполняться чаще. 🛠 Как это выглядит в коде? Обычно ошибки и проверки аргументов (Guard Clauses) срабатывают редко. Это идеальное место для [[unlikely]].

void ProcessImage(Image* img) {
    // 1. Проверка на null.
    // Это случается редко, помечаем как "маловероятно".
    if (img == nullptr) [[unlikely]] {
        return; // Компилятор уведет этот код "подальше" из горячего пути
    }

    // 2. Еще одна проверка
    if (img->IsEmpty()) [[unlikely]] {
        return;
    }

    // --- Happy Path ---
    // Процессор сразу прыгнет сюда, ожидая, что проверки выше ложны.
    img->ApplyFilter();
    img->Save();
}

⚙️ Что происходит под капотом? Компилятор переставит инструкции ассемблера так, чтобы «счастливый путь» шел линейно, без прыжков (jmp), что улучшает работу кэша инструкций. Код обработки ошибок (ветка [[unlikely]]) будет сдвинут в конец функции или в «холодную» зону. ⚠️ Важный нюанс: Используйте это только тогда, когда вы уверены в вероятностях (например, ошибки случаются в 1 случае из 1000). Если поставить атрибуты наугад, можно сделать только хуже (pessimization). 🔥 Итог: Чистый код (Early Return) + Подсказки компилятору ([[unlikely]]) = Читаемость и Производительность. #cpp #cpp20 #coding #optimization #tips #programming ➡️ @cpp_geek

🔥 Оптимизация кода на C++: Ранний возврат вместо вложенных условий Привет, друзья! Сегодня хочу поговорить об одной важной технике, которая делает код чище и читабельнее — ранний возврат (early return). Часто встречаю код, который уходит в глубину вложенных if, превращаясь в настоящий лабиринт. Давайте разберем, как этого избежать. ❌ Плохой пример: Вложенные условия

void process(int value) {
    if (value > 0) {
        if (value % 2 == 0) {
            if (value < 100) {
                std::cout << "Обрабатываем " << value << std::endl;
            } else {
                std::cout << "Слишком большое число" << std::endl;
            }
        } else {
            std::cout << "Нечетное число" << std::endl;
        }
    } else {
        std::cout << "Отрицательное число" << std::endl;
    }
}
Здесь код уходит вглубь из-за множества вложенных if, что делает его сложным для чтения. ✅ Хороший пример: Ранний возврат

void process(int value) {
    if (value <= 0) {
        std::cout << "Отрицательное число" << std::endl;
        return;
    }
    if (value % 2 != 0) {
        std::cout << "Нечетное число" << std::endl;
        return;
    }
    if (value >= 100) {
        std::cout << "Слишком большое число" << std::endl;
        return;
    }

    std::cout << "Обрабатываем " << value << std::endl;
}
Теперь код сразу проверяет граничные условия и делает ранний возврат (return), если условия не выполнены. В итоге у нас получился плоский код, который проще читать и сопровождать. 🎯 Вывод: - Избегайте вложенных if, если можно этого не делать. - Используйте ранний возврат, чтобы код был линейным и понятным. - Чем меньше уровней вложенности — тем легче отладка и сопровождение. ➡️ @cpp_geek

Улучшенные версии STL-контейнеров из библиотеки Boost Илья Мещерин В любом учебном курсе по C++, даже начального уровня, обязательно изучают, как устроен std::vector. Детали внутреннего устройства std::vector в подробностях продолжают изучать в вузах, спрашивать на собеседованиях, обсуждать на конференциях. То же самое происходит с контейнерами std::list, std::deque, std::map и std::unordered_map: про их реализацию и особенности внутреннего устройства можно говорить бесконечно долго, про них все еще делают доклады, снимают лекции и пишут статьи. И их продолжают использовать в продакшен-коде даже в самых крупных и известных компаниях. При этом в библиотеке Boost давным-давно есть альтернативные версии контейнеров, которые выигрывают у стандартных по многим показателям. Однако об этих версиях почти никто не знает, о них почти нет лекций, статей и докладов. Пора положить этому конец и разобраться в том, как еще могут быть устроены контейнеры, помимо тех версий из STL, о которых и так все знают. Спикер обсудил внутреннее устройство не таких уж стандартных контейнеров: stable_vector, devector, bimap, circular_buffer, а также интрузивных версий list, map, unordered_map и их разновидностей. источник ➡️ @cpp_geek

🚀Это отличный ресурс для программистов, работающих с C++. Можно найти подробную документацию по стандартной библиотеке, STL,
🚀Это отличный ресурс для программистов, работающих с C++. Можно найти подробную документацию по стандартной библиотеке, STL, различным версиям стандарта C++, а также примеры кода и объяснения по ключевым аспектам языка. Справочник по C++ C++11, C++14, C++17, C++20, C++23, C++26 │ Поддержка компиляторами C++11, C++14, C++17, C++20, C++23, C++26 Справочник по языку C C89, C95, C99, C11, C17, C23 │ Поддержка компиляторами C99, C23 https://ru.cppreference.com/w/ ➡️ @cpp_geek

Присоединяйтесь к встрече РГ21 С++ в Москве 15 декабря Антон Полухин (Яндекс) выступит с новостями со встречи международного
Присоединяйтесь к встрече РГ21 С++ в Москве 15 декабря Антон Полухин (Яндекс) выступит с новостями со встречи международного Комитета по стандартизации C++: расскажет о прогрессе в работе по C++26, о том, какие комментарии по стандарту от России были внесены, и о внезапных новинках. После выступления Антон ответит на вопросы о том, как российские разработчики могут участвовать в развитии стандарта. Также в программе заложено время для открытого обсуждения доклада и неформального общения участников. Успейте зарегистрироваться до 15 декабря.

📌 Оптимизация кода в C++: Используем std::move правильно! Привет, друзья! Сегодня я расскажу об одной из самых частых ошибок, связанных с std::move. Многие знают, что std::move не перемещает объект, а лишь превращает его в rvalue. Но как его использовать правильно? Давайте разбираться! ❌ Ошибка: Бессмысленный std::move

std::string getString() {
    std::string str = "Hello, world!";
    return std::move(str); // ❌ Неэффективно
}
Что здесь не так? Возвращаемый std::string и так является временным объектом (NRVO — оптимизация возврата), и std::move мешает этой оптимизации! В результате компилятор не сможет выполнить перемещение, а вызовет копирование. ✅ Правильный вариант:

std::string getString() {
    return "Hello, world!"; // ✅ NRVO оптимизация
}
🏆 Где std::move полезен? Используйте std::move, когда точно знаете, что объект больше не нужен и его можно переместить:

void processString(std::string str) { /* ... */ }

int main() {
    std::string s = "Example";
    processString(std::move(s)); // 🔥 Теперь перемещение!
}
1️⃣ Не используйте std::move при возврате локальных объектов — дайте компилятору сделать свое дело! 2️⃣ Используйте std::move, когда объект больше не нужен — это ускорит работу кода. 3️⃣ После std::move не используйте переменную, кроме как для присвоения нового значения. ➡️ @cpp_geek

🔥 Оптимизация кода на C++: Ранний возврат вместо вложенных условий Привет, друзья! Сегодня хочу поговорить об одной важной технике, которая делает код чище и читабельнее - ранний возврат (early return). Часто встречаю код, который уходит в глубину вложенных if, превращаясь в настоящий лабиринт. Давайте разберем, как этого избежать. ❌ Плохой пример: Вложенные условия

void process(int value) {
    if (value > 0) {
        if (value % 2 == 0) {
            if (value < 100) {
                std::cout << "Обрабатываем " << value << std::endl;
            } else {
                std::cout << "Слишком большое число" << std::endl;
            }
        } else {
            std::cout << "Нечетное число" << std::endl;
        }
    } else {
        std::cout << "Отрицательное число" << std::endl;
    }
}
Здесь код уходит вглубь из-за множества вложенных if, что делает его сложным для чтения. ✅ Хороший пример: Ранний возврат

void process(int value) {
    if (value <= 0) {
        std::cout << "Отрицательное число" << std::endl;
        return;
    }
    if (value % 2 != 0) {
        std::cout << "Нечетное число" << std::endl;
        return;
    }
    if (value >= 100) {
        std::cout << "Слишком большое число" << std::endl;
        return;
    }

    std::cout << "Обрабатываем " << value << std::endl;
}
Теперь код сразу проверяет граничные условия и делает ранний возврат (return), если условия не выполнены. В итоге у нас получился плоский код, который проще читать и сопровождать. 🎯 Вывод: - Избегайте вложенных if, если можно этого не делать. - Используйте ранний возврат, чтобы код был линейным и понятным. - Чем меньше уровней вложенности - тем легче отладка и сопровождение. ➡️ @cpp_geek

🔥 Оптимизация кода на C++: Ранний возврат вместо вложенных условий Привет, друзья! Сегодня хочу поговорить об одной важной технике, которая делает код чище и читабельнее — ранний возврат (early return). Часто встречаю код, который уходит в глубину вложенных if, превращаясь в настоящий лабиринт. Давайте разберем, как этого избежать. ❌ Плохой пример: Вложенные условия

void process(int value) {
    if (value > 0) {
        if (value % 2 == 0) {
            if (value < 100) {
                std::cout << "Обрабатываем " << value << std::endl;
            } else {
                std::cout << "Слишком большое число" << std::endl;
            }
        } else {
            std::cout << "Нечетное число" << std::endl;
        }
    } else {
        std::cout << "Отрицательное число" << std::endl;
    }
}
Здесь код уходит вглубь из-за множества вложенных if, что делает его сложным для чтения. ✅ Хороший пример: Ранний возврат

void process(int value) {
    if (value <= 0) {
        std::cout << "Отрицательное число" << std::endl;
        return;
    }
    if (value % 2 != 0) {
        std::cout << "Нечетное число" << std::endl;
        return;
    }
    if (value >= 100) {
        std::cout << "Слишком большое число" << std::endl;
        return;
    }

    std::cout << "Обрабатываем " << value << std::endl;
}
Теперь код сразу проверяет граничные условия и делает ранний возврат (return), если условия не выполнены. В итоге у нас получился плоский код, который проще читать и сопровождать. 🎯 Вывод: - Избегайте вложенных if, если можно этого не делать. - Используйте ранний возврат, чтобы код был линейным и понятным. - Чем меньше уровней вложенности — тем легче отладка и сопровождение. ➡️ @cpp_geek

📌 Оптимизация кода: std::string_view вместо std::string Привет, друзья! Сегодня хочу рассказать про std::string_view — полезный инструмент, который может значительно ускорить работу с строками в C++. Многие из вас, вероятно, используют std::string, но не всегда это лучший выбор. ❓ Что такое std::string_view? Это некопируемая, легковесная оболочка над строковыми данными. Она просто хранит указатель на начало строки и её длину, не создавая копии. Использование std::string_view вместо std::string позволяет избежать ненужных аллокаций памяти и ускорить код. 🔥 Пример использования:

#include <iostream>
#include <string_view>

void print(std::string_view str) {  // Без лишнего копирования
    std::cout << str << '\n';
}

int main() {
    std::string s = "Hello, world!";
    print(s);         // Можно передавать std::string
    print("Hi there"); // Можно передавать строковый литерал
}
🛠 Когда использовать? ✅ При передаче строк в функции, если их не нужно модифицировать. ✅ Для работы с подстроками (в отличие от std::string::substr, который делает копию). ✅ Для обработки строк без создания динамических объектов. ⚠️ Важно помнить: - std::string_view не владеет данными, поэтому нельзя использовать его для длительного хранения указателей на временные строки. - Нужно быть осторожным с объектами, чей срок жизни может закончиться, пока std::string_view ещё используется. 🚀 Итог: Использование std::string_view вместо const std::string& может ускорить работу с текстовыми данными и снизить нагрузку на аллокатор. Если не нужно изменять строку — это отличный выбор! А вы уже используете std::string_view в своих проектах? Делитесь в комментариях! ⬇️ ➡️ @cpp_geek

📌 Уменьшаем размер исполняемого файла в C++ Всем добрый вечер! Хочу поделиться парой трюков, которые помогут уменьшить размер исполняемого файла вашей программы на C++. Это полезно, если вы пишете под встраиваемые системы, создаёте утилиты или просто хотите более компактный бинарник. 🔹 1. Отключаем отладочную информацию Компиляторы по умолчанию добавляют отладочные символы в бинарник. Их можно убрать флагами:

g++ -o my_program my_program.cpp -O2 -s
Флаг -s удаляет все отладочные символы. 🔹 2. Оптимизируем код Используйте -O2 или -Os, чтобы компилятор оптимизировал код для уменьшения размера:

g++ -o my_program my_program.cpp -Os
Флаг -Os специально оптимизирует код для минимального размера. 🔹 3. Статическая или динамическая линковка? Если в системе уже есть нужные библиотеки, используйте динамическую линковку (-shared для .so в Linux, /MD в MSVC). Но иногда статическая линковка (флаг -static) позволяет избавиться от лишних зависимостей. 🔹 4. Убираем ненужные зависимости Можно использовать strip, чтобы дополнительно очистить бинарник:

strip my_program
А ещё, если пишете на C++, то не забывайте про -ffunction-sections -fdata-sections и --gc-sections, чтобы убрать неиспользуемый код. 🔹 5. Убираем RTTI и исключения Если не используете dynamic_cast и исключения, отключите их:

g++ -o my_program my_program.cpp -Os -fno-rtti -fno-exceptions
Это существенно уменьшит размер! ➡️ @cpp_geek

📌 Оптимизация использования std::unordered_map в C++ Сегодня я расскажу вам, как оптимизировать работу std::unordered_map и избежать неожиданных тормозов. std::unordered_map — мощная хеш-таблица в C++, но при неправильном использовании она может замедлить ваш код. Давайте разберем основные моменты, которые помогут избежать проблем. 🔥 1. Выбирайте правильный хеш-функтор По умолчанию std::unordered_map использует std::hash<Key>, но если ключ — это пользовательский тип данных (например, struct`), то стандартного `std::hash не существует, и придется писать свой. Пример кастомного хеша для структуры:

struct MyKey {
    int x, y;

    bool operator==(const MyKey& other) const {
        return x == other.x && y == other.y;
    }
};

struct MyHash {
    size_t operator()(const MyKey& key) const {
        return std::hash<int>{}(key.x) ^ (std::hash<int>{}(key.y) << 1);
    }
};

std::unordered_map<MyKey, std::string, MyHash> my_map;
Используем ^ (XOR) и << (битовый сдвиг), чтобы уменьшить коллизии. ⚡ 2. Контролируйте размер bucket'ов Если std::unordered_map сильно увеличивается, он перехеширует (rehash), что может быть дорогой операцией. Чтобы избежать лишних перераспределений:

my_map.reserve(10000); // Подготавливаем место под 10,000 элементов
Это ускорит вставку, так как уменьшит количество перераспределений памяти. 🚀 3. Избегайте ненужного копирования ключей Если ключ — это сложный объект, избегайте его копирования:

std::unordered_map<std::string, int> data;
std::string key = "long_key_string";

int value = data[key]; // ❌ НЕ ЭФФЕКТИВНО: создаст пустую запись, если ключа нет
int value = data.at(key); // ✅ БЫСТРЕЕ: выбросит исключение, если ключа нет
Еще лучше использовать find():

auto it = data.find(key);
if (it != data.end()) {
    int value = it->second;
}
🏆 Вывод ✅ Используйте кастомные хеш-функции, если ключи нестандартные ✅ Резервируйте память заранее (reserve) ✅ Уменьшайте копирование ключей, используя find() и at() А вы используете std::unordered_map в своих проектах? Может, у вас есть свои фишки? Пишите в комментариях! 👇🚀 ➡️ @cpp_geek

📌 Оптимизация кода: стоит ли всегда инлайнить функции? Привет, сегодня поговорим о inline функциях в C++. Часто вижу, как новички (да и не только) злоупотребляют этим ключевым словом. Давайте разберемся, стоит ли всегда использовать inline для оптимизации кода. 🔎 Что делает inline? Когда вы помечаете функцию как inline, компилятор может (но не обязан) заменить вызовы этой функции её телом, чтобы избежать накладных расходов на вызов. 🔥 Когда inline полезен? ✅ Очень короткие функции (1-2 строчки). Например:

inline int square(int x) { return x * x; }
Геттеры и сеттеры в классах, если они простые. ✅ Функции-хелперы в заголовочных файлах (например, в `namespace`-ах). ⚠️ Когда inline во вред? ❌ Большие функции. Раздувает бинарник, увеличивает время компиляции. ❌ Часто изменяемый код. Так как `inline`-функции вставляются в код, изменение их логики требует перекомпиляции всех файлов, где они были вызваны. ❌ Чрезмерное использование. Вставка слишком многих `inline`-функций может снизить эффективность процессорного кеша, что приведет к ухудшению производительности. 🎯 Альтернатива: constexpr! В C++11 появился constexpr, который не только инлайнит, но и выполняет вычисления на этапе компиляции:

constexpr int cube(int x) { return x * x * x; }
Если можете сделать функцию constexpr — делайте, это лучше, чем просто inline! 🤔 Итог inline — мощный инструмент, но применять его стоит с умом. Лучше доверять компилятору и включить оптимизацию -O2 или -O3, чем разбрасываться inline без разбора. ➡️ @cpp_geek

Запустите рекламу в телеграм-каналах с Яндекс Директом Перфоманс-реклама теперь в телеграм-каналах ⚡ Яндекс Директ знает, как
Запустите рекламу в телеграм-каналах с Яндекс Директом Перфоманс-реклама теперь в телеграм-каналах ⚡ Яндекс Директ знает, как привлечь целевую аудиторию 💰👌 Попробовать #реклама yandex.ru О рекламодателе

Что такое TCP Server Project в C++? 💬 TCP Server Project — это проект, который реализует сервер для обмена данными по протоколу TCP (Transmission Control Protocol). Такой сервер позволяет клиентам подключаться к нему, отправлять запросы и получать ответы через надёжное соединение. На практике TCP-сервер в C++ создаётся с помощью сокетов (например, используя Berkeley sockets на Linux или Winsock на Windows). Процесс обычно включает: • Создание сокета — создаётся дескриптор для коммуникации. • Привязка к порту (bind) — сервер привязывается к определённому порту на хосте. • Прослушивание соединений (listen) — сервер ожидает входящие подключения. • Принятие соединений (accept) — сервер принимает запросы от клиентов. • Обмен данными — сервер и клиент обмениваются сообщениями через соединение. 📌 Пример применения: чаты, игровые серверы, веб-серверы и любые приложения, требующие стабильного соединения с гарантией доставки данных. ➡️ @cpp_geek

🔥 Как правильно сравнивать std::string в C++? Доброй ночи! Давайте разберём важную тему – сравнение std::string в C++. Многие думают, что это просто (== и всё), но есть нюансы! Давайте разберёмся. ✅ Способы сравнения строк 1️⃣ Оператор == Если вам нужно проверить точное совпадение строк:

std::string str1 = "hello";
std::string str2 = "hello";

if (str1 == str2) {
    std::cout << "Строки равны!\n";
}
Этот метод безопасен, читабелен и работает быстро. 2️⃣ Функция compare() Если нужно получить порядок строк в алфавитном сравнении:

std::string str1 = "apple";
std::string str2 = "banana";

if (str1.compare(str2) < 0) {
    std::cout << "apple идет перед banana\n";
}
🔹 compare() возвращает: - 0, если строки равны - < 0, если str1 меньше str2 - > 0, если str1 больше str2 3️⃣ Сравнение без учета регистра В C++ нет встроенного метода, но можно использовать std::transform:

#include <algorithm>
#include <cctype>
#include <string>

bool caseInsensitiveCompare(const std::string& a, const std::string& b) {
    return std::equal(a.begin(), a.end(), b.begin(), b.end(),
                      [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); });
}

std::string str1 = "Hello";
std::string str2 = "hello";

if (caseInsensitiveCompare(str1, str2)) {
    std::cout << "Строки равны без учета регистра!\n";
}
4️⃣ Сравнение подстрок Если нужно проверить, начинается ли строка с подстроки:

std::string text = "hello world";
std::string prefix = "hello";

if (text.rfind(prefix, 0) == 0) {
    std::cout << "Строка начинается с 'hello'!\n";
}
rfind(prefix, 0) == 0 проверяет, что prefix стоит в начале строки. 🚀 Итоги ✔ Используйте == для простого сравнения ✔ compare() – если важно узнать порядок ✔ Для регистра – std::tolower() ✔ Для подстрок – rfind() Какой метод вы чаще используете? Делитесь в комментариях! ➡️ @cpp_geek

🔥 C++: умные указатели – избавляемся от delete навсегда! Вы все еще вручную освобождаете память? Это уже не актуально! Разбираем умные указатели (std::unique_ptr, std::shared_ptr) и их преимущества. 🔹 std::unique_ptr – для объектов, у которых один владелец. Память освобождается автоматически, когда указатель выходит из области видимости:

#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(42);
    std::cout << *ptr << std::endl; // 42
}
🔹 std::shared_ptr – для объектов, у которых несколько владельцев. Когда последний shared_ptr уничтожается – объект тоже удаляется:

#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> sp1 = std::make_shared<int>(42);
    std::shared_ptr<int> sp2 = sp1; // Теперь два владельца

    std::cout << *sp1 << " " << *sp2 << std::endl; // 42 42
}
❌ Забудьте про new и delete, используйте std::make_unique и std::make_shared. Это избавит вас от утечек памяти. А вы уже полностью отказались от delete? Пишите в комментариях! 👇 ➡️ @cpp_geek

Для чего нужен алгоритм generate? Используется для генерации чисел на основе функции генератора, а затем присваивает эти знач
Для чего нужен алгоритм generate? Используется для генерации чисел на основе функции генератора, а затем присваивает эти значения элементам в контейнере в диапазоне [first, last). ➡️ @cpp_geek

Pipes В C++ пайпы (pipes) представляют собой механизм для односторонней связи между процессами. Они позволяют передавать данн
Pipes В C++ пайпы (pipes) представляют собой механизм для односторонней связи между процессами. Они позволяют передавать данные из одного процесса в другой, где один процесс выступает в роли писателя (write end), а другой процесс выступает в роли читателя (read end) пайпа. Для работы с пайпами вы можете использовать системные вызовы, такие как pipe, fork и функции чтения/записи (read и write), доступные в POSIX-совместимых операционных системах. Обратите внимание, что дескрипторы чтения и записи пайпа должны быть закрыты в соответствующих процессах с помощью close, чтобы гарантировать правильное завершение операций чтения и записи. ➡️ @cpp_geek