<MyRusakov.ru />

Программирование на C++ в Unreal Engine 5

Программирование на C++ в Unreal Engine 5

Данный курс научит Вас созданию игр на C++ в Unreal Engine 5. Курс состоит из 12 разделов, в которых Вас ждёт теория и практика. Причём, в качестве практики будет создан весьма крупный проект объёмом свыше 5000 строк качественного кода, который уже на практике познакомит Вас с принципами создания игр на C++ в Unreal Engine 5.

Параллельно с курсом Вы также будете получать домашние задания, результатом которых станет, в том числе, полноценная серьёзная работа для портфолио.

Помимо самого курса Вас ждёт ещё и очень ценный Бонус: «Тестирование Unreal-проектов на Python», в рамках которого Вы научитесь писать очень полезные тесты для тестирования самых разных аспектов разработки игр.

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

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

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

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

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

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

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

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

std::string и std::string_view в C++: разница, производительность и безопасные паттерны

std::string и std::string_view в C++: разница, производительность и безопасные паттерны

Запрос «string_view в C++: когда использовать и чем он лучше std::string» — один из самых частых у начинающих. Разобраться важно: от правильного выбора типа зависит и производительность, и безопасность кода. В этой статье мы сравним std::string и std::string_view, разберёмся с владением, временем жизни, покажем практичные примеры и типичные ошибки.

Ключевая идея: владение против представления

  • std::string — владеет буфером (динамическая память), отвечает за выделение/освобождение, изменяемый.
  • std::string_viewневладеющее представление (указатель + длина). Ничего не копирует и не освобождает. Только «смотрит» на чужие данные.

Из этого следует правило: если функция только читает строку, удобнее принимать std::string_view. Если нужно хранить, модифицировать или продлить жизнь данных — используйте std::string.

Создание и совместимость

std::string_view легко строится из строковых литералов, std::string и C‑строк:

#include <string>
#include <string_view>

void f(std::string_view sv);

int main() {
    std::string s = "hello";
    const char* c = "world";

    f(s);          // из std::string
    f(c);          // из C-строки
    f("literal"); // из литерала
}

Обратное преобразование (view → string) требует копирования:

std::string_view sv = "data";
std::string owned = std::string(sv); // копия, владение теперь у owned

Где string_view особенно полезен

1) Входные параметры без копий

#include <string_view>
#include <cctype>

// Подсчёт слов: разделитель — пробельный символ
size_t count_words(std::string_view text) {
    size_t count = 0;
    bool in_word = false;
    for (unsigned char ch : text) {
        if (std::isspace(ch)) {
            in_word = false;
        } else if (!in_word) {
            in_word = true;
            ++count;
        }
    }
    return count;
}

Функция принимает и std::string, и литералы, и C-строки без лишних копий.

2) Быстрый trim без аллокаций

#include <string_view>
#include <cctype>

std::string_view trim(std::string_view sv) {
    auto is_space = [](unsigned char c){ return std::isspace(c); };
    while (!sv.empty() && is_space(sv.front())) sv.remove_prefix(1);
    while (!sv.empty() && is_space(sv.back()))  sv.remove_suffix(1);
    return sv; // всё ещё view на исходные данные
}

3) Лёгкий сплит по разделителю

#include <string_view>
#include <vector>

std::vector<std::string_view> split(std::string_view sv, char delim) {
    std::vector<std::string_view> parts;
    size_t start = 0;
    while (true) {
        size_t pos = sv.find(delim, start);
        if (pos == std::string_view::npos) {
            parts.push_back(sv.substr(start));
            break;
        }
        parts.push_back(sv.substr(start, pos - start));
        start = pos + 1;
    }
    return parts; // вектора view; копий строк нет
}

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

Опасные места и как их избежать

1) Возврат view на временные данные — ошибка

// ПЛОХО: возвращаем view на локальный std::string
std::string_view bad() {
    std::string s = "temp";
    return s; // висячая ссылка (dangling)
}

Правильно: вернуть std::string (владеющий) или принять буфер снаружи.

// Хорошо: возвращаем владение
std::string good() {
    std::string s = "ok";
    return s; // RVO/NRVO, без лишней копии
}

2) Долгое хранение string_view

std::string make()
{
    std::string s = "hello";
    return s;
}

std::string_view sv;
{
    std::string tmp = make();
    sv = tmp; // sv указывает внутрь tmp
} // tmp разрушен — sv теперь висячий

Решение: если нужно хранить — храните std::string или делайте копию:

std::string owned;
{
    std::string tmp = make();
    owned = tmp; // корректно
}

3) Реаллокиация ломает все view

std::string s = "abc";
std::string_view v = s; // указывает внутрь s
s += "def";            // возможна реаллокация буфера
// v может стать недействительным

Вывод: не храните string_view на строку, которую планируется изменять (push_back, append, resize и т.п.).

Производительность: когда реально быстрее

  • Создание/копирование std::string_view — O(1).
  • Подстроки через substr у view — O(1), без копирования данных.
  • Копирование std::string — O(N), выделение памяти, перенос байтов.

Поэтому в API для чтения данных используйте string_view. В местах, где нужны собственные данные или модификация — string.

Интероп с C‑API: c_str() и data()

  • std::string::c_str() и data() в C++17 возвращают нуль-терминированный буфер (const char*).
  • std::string_view::data() — указатель на первый символ без гарантии завершающего нуля.
extern "C" void c_api(const char*);

std::string s = "hello";
c_api(s.c_str()); // ок

std::string_view sv = "world";
// c_api(sv.data()); // может не содержать '\0' в конце — небезопасно
// Решение: скопировать
std::string tmp(sv);
c_api(tmp.c_str());

Практика: парсинг ключ=значение без копий

#include <string_view>
#include <optional>
#include <utility>

std::optional<std::pair<std::string_view, std::string_view>>
parse_kv(std::string_view sv) {
    auto pos = sv.find('=');
    if (pos == std::string_view::npos) return std::nullopt;
    auto key = sv.substr(0, pos);
    auto val = sv.substr(pos + 1);
    return std::make_pair(trim(key), trim(val));
}

Функция возвращает пары view; при необходимости сохранения значений — скопируйте их в std::string.

Частые вопросы

Можно ли модифицировать через string_view? Нет. Это read-only представление. Если нужно изменить — используйте string или span к изменяемому буферу.

Как быть с Unicode? std::string — это просто байты. Операции size(), substr() работают по байтам, а не по кодовым точкам. Для Unicode учитывайте кодировку (UTF‑8) и используйте специализированные библиотеки.

Рекомендации и паттерны

  • В публичном API для входных строк — std::string_view.
  • Не храните string_view дольше жизни источника; не используйте его на изменяемую строку.
  • Нужна долговременная копия — явный std::string.
  • Для C‑API используйте c_str() у std::string; у string_view при необходимости делайте копию.
  • Профилируйте: string_view ускоряет код, убирая копии. Но не жертвуйте безопасностью времени жизни.

Хотите системно прокачать основы C++ (типы, ссылки, строки, память, ООП) и практику на проектах? Загляните в пошаговый курс «C++ с Нуля до Гуру» — от синтаксиса к реальным задачам.

Итоги

std::string — для владения и модификации. std::string_view — для чтения без копий. Соблюдайте правила времени жизни и не храните view «на будущее». С этими принципами ваш код станет одновременно быстрее и надёжнее.

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

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

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

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

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

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

  1. Кнопка:

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

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

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

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

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

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