<MyRusakov.ru />

Создание игр на Unreal Engine 5

Создание игр на Unreal Engine 5

Данный курс научит Вас созданию игр на Unreal Engine 5. Курс состоит из 12 модулей, в которых Вы с нуля освоите этот движок и сможете создавать самые разные игры.

В курсе Вы получите всю необходимую теоретическую часть, а также увидите массу практических примеров. Дополнительно, почти к каждому уроку идут упражнения для закрепления материала.

Помимо самого курса Вас ждёт ещё 8 бесплатных ценных Бонусов: «Chaos Destruction», «Разработка 2D-игры», «Динамическая смена дня и ночи», «Создание динамической погоды», «Создание искусственного интеллекта для NPC», «Создание игры под мобильные устройства», «Создание прототипа RPG с открытым миром» и и весь курс «Создание игр на Unreal Engine 4» (актуальный и в 5-й версии), включающий в себя ещё десятки часов видеоуроков.

Подробнее
Подписка

Подпишитесь на мой канал на YouTube, где я регулярно публикую новые видео.

YouTube Подписаться

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Какая тема Вас интересует больше?

RAII в C++ простыми словами: как управлять ресурсами без утечек

RAII в C++ простыми словами: как управлять ресурсами без утечек

Ключевой запрос: RAII в C++ простыми словами.

RAII — базовый принцип C++, который избавляет от ручного освобождения ресурсов. Идея: ресурс привязан к объекту; конструктор получает ресурс, а деструктор гарантированно освобождает его. Благодаря этому код становится короче, безопаснее и устойчивее к исключениям.

Что такое RAII в C++ простыми словами

RAII расшифровывается как Resource Acquisition Is Initialization — «получение ресурса есть инициализация». Как только вы создали объект, он «владеет» ресурсом. Когда объект выходит из области видимости, его деструктор автоматически освобождает ресурс — даже если произошёл return или исключение.

Какие ресурсы считаются «ресурсами»

  • Память (heap-объекты)
  • Файлы и дескрипторы
  • Мьютексы и другие синхронизационные примитивы
  • Сокеты, соединения с БД, таймеры и т.п.

Антипример: утечка при исключении

Ручное управление часто приводит к утечкам, особенно при исключениях. Посмотрите, как легко ошибиться:

#include <cstdio>
#include <stdexcept>

void process_bad() {
    FILE* f = std::fopen("data.txt", "r");
    if (!f) throw std::runtime_error("cannot open");

    char buf[128];
    if (!std::fgets(buf, sizeof(buf), f)) {
        std::fclose(f);
        throw std::runtime_error("read error");
    }

    if (buf[0] == '#') {
        // ранний выход через исключение — забыли закрыть файл!
        throw std::runtime_error("special case"); // утечка: fclose не вызван
    }

    std::fclose(f);
}

Здесь легко пропустить std::fclose на одном из путей выполнения. RAII решает это автоматически.

Правильный подход: свой RAII-объект

Оборачиваем ресурс в класс-обёртку, который закрывает файл в деструкторе.

#include <cstdio>
#include <stdexcept>

class File {
    FILE* f = nullptr;
public:
    File(const char* path, const char* mode) {
        f = std::fopen(path, mode);
        if (!f) throw std::runtime_error("cannot open file");
    }
    ~File() {
        if (f) std::fclose(f); // освобождение ресурса гарантировано
    }
    File(const File&) = delete;
    File& operator=(const File&) = delete;

    File(File&& other) noexcept : f(other.f) { other.f = nullptr; }
    File& operator=(File&& other) noexcept {
        if (this != &other) {
            if (f) std::fclose(f);
            f = other.f;
            other.f = nullptr;
        }
        return *this;
    }

    FILE* get() const noexcept { return f; }
};

void process_good() {
    File file("data.txt", "r");
    char buf[128];
    if (!std::fgets(buf, sizeof(buf), file.get())) {
        throw std::runtime_error("read error");
    }
    if (buf[0] == '#') {
        throw std::runtime_error("special case");
    }
} // здесь деструктор File закроет файл даже при исключении

Почему это работает

  • Деструкторы вызываются автоматически при выходе из области видимости
  • Копирование запрещено — значит, у ресурса один владелец
  • Перемещение разрешено — можно безопасно передавать владение

RAII в стандартной библиотеке: используйте готовое

  • Файлы: std::ifstream, std::ofstream сами закрывают файл в деструкторе
  • Память: std::unique_ptr<T> освобождает память автоматически
  • Мьютексы: std::lock_guard<std::mutex> и std::scoped_lock освобождают блокировку при выходе из области видимости
#include <mutex>
#include <thread>
#include <vector>

std::mutex m;
int counter = 0;

void inc() {
    std::lock_guard<std::mutex> lock(m); // захват мьютекса по RAII
    ++counter;                           // освобождение при выходе из функции
}

int main() {
    std::vector<std::thread> ths;
    for (int i = 0; i < 10; ++i) ths.emplace_back(inc);
    for (auto& t : ths) t.join();
}

Коротко о памяти по RAII:

#include <memory>

std::unique_ptr<int> p = std::make_unique<int>(42); // delete не нужен

Хотя умные указатели — отдельная большая тема, важно понимать: они — готовая реализация RAII для памяти.

Мини-паттерн: Scope Guard за 10 строк

Иногда нужен одноразовый «крючок» на выход из блока. Сделаем мини-guard:

#include <utility>
#include <cstdio>

template <class F>
class ScopeGuard {
    F f; bool active = true;
public:
    explicit ScopeGuard(F&& func) : f(std::forward<F>(func)) {}
    ~ScopeGuard() { if (active) f(); }
    void dismiss() noexcept { active = false; }
};

template <class F>
ScopeGuard<F> make_guard(F&& f) { return ScopeGuard<F>(std::forward<F>(f)); }

void demo_guard() {
    FILE* f = std::fopen("data.txt", "r");
    if (!f) return;
    auto guard = make_guard([&] { std::fclose(f); });
    // ... любая логика, в т.ч. исключения
    // guard автоматически закроет файл
}

Советы и лучшие практики

  • Не храните «сырой» ресурс напрямую в коде — заверните в класс или используйте готовые RAII-обёртки из STL
  • Деструкторы должны быть noexcept — не бросайте исключения из деструктора
  • Следуйте правилу нуля: если возможно, не пишите явные деструкторы/копии/перемещения — пусть всё делает стандартный контейнер или умный указатель
  • Один владелец — одно освобождение: запретите копирование для уникальных ресурсов (= delete), разрешайте перемещение при необходимости
  • Не вызывайте вручную close/free/delete там, где уже есть RAII — это ведёт к двойному освобождению
  • Выбирайте минимальный объём владения: объект должен управлять только тем, за что несёт ответственность

Частые ошибки

  • Двойное освобождение: вручную вызываете close, а затем срабатывает деструктор
  • Использование после перемещения: перемещённый объект остаётся валидным, но ресурс уехал — используйте его осторожно
  • Смешивание стилей: часть кода на RAII, часть — на ручном управлении. Придерживайтесь одного подхода — RAII

Итоги и что дальше

RAII — краеугольный камень безопасного и лаконичного C++. Он снимает боль с освобождением ресурсов, делает код устойчивым к исключениям и сокращает число ошибок. Начинайте применять RAII везде: для файлов, памяти, мьютексов и сетевых дескрипторов — и код станет надёжнее уже сегодня.

Хотите быстро закрепить RAII и другие основы на практике, с проектами и разбором ошибок? Рекомендую программу с пошаговыми заданиями: Прокачать C++ на практике — курс «С Нуля до Гуру».

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (https://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: https://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: https://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.