<MyRusakov.ru />

WordPress 6 с Нуля до Гуру

WordPress 6 с Нуля до Гуру

Этот курс научит Вас созданию самых разных сайтов на самой популярной в мире CMS - WordPress. Вы увидите установку и настройку локального сервера, разбор каждой настройки, каждой кнопки и каждого пункта меню в панели WordPress.

Также Вы получите и всю практику, поскольку прямо в курсе с нуля создаётся полноценный Интернет-магазин, который затем публикуется в Интернете. И всё это прямо на Ваших глазах.

Помимо уроков к курсу идут упражнения для закрепления материала.

И, наконец, к курсу идёт ценнейший Бонус по тому, как используя ChatGPT и создавая контент для сайта, можно выйти на пассивный доход. Вы наглядно увидите, как зарегистрироваться в ChatGPT (в том числе, и если Вы из России), как правильно выбрать тему для сайта, как правильно генерировать статьи для него(чтобы они индексировались поисковыми системами) и как правильно монетизировать трафик на сайте.

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

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

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

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

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

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

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

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

std::optional в C++17: как безопасно работать с отсутствующим значением

std::optional в C++17: как безопасно работать с отсутствующим значением

Поисковый запрос «std::optional C++ примеры» обычно возникает, когда разработчик хочет вернуть из функции «значение или ничего». До C++17 для этого часто использовали -1, пустую строку, nullptr или отдельный bool-флаг. Такой код работает, но легко ломается: вызывающий может забыть проверить результат или перепутать «настоящее» значение с признаком ошибки.

std::optional — это контейнер для одного значения, которое либо есть, либо отсутствует. Он находится в заголовке <optional> и доступен начиная с C++17.

Зачем нужен std::optional

Представим функцию, которая ищет позицию символа в строке. Плохой вариант — вернуть -1, если символ не найден:

int findChar(const std::string& text, char ch) {
    for (int i = 0; i < static_cast<int>(text.size()); ++i) {
        if (text[i] == ch) return i;
    }
    return -1; // магическое значение
}

Проблема в том, что -1 — это договорённость, которую нужно помнить. С std::optional намерение видно прямо в типе:

#include <optional>
#include <string>

std::optional<std::size_t> findChar(const std::string& text, char ch) {
    for (std::size_t i = 0; i < text.size(); ++i) {
        if (text[i] == ch) return i;
    }
    return std::nullopt;
}

Тип std::optional<std::size_t> буквально говорит: функция может вернуть индекс, а может не вернуть ничего.

Как проверить, есть ли значение

Самый простой способ — использовать optional в условии:

#include <iostream>

int main() {
    auto pos = findChar("hello", 'e');

    if (pos) {
        std::cout << "Символ найден на позиции: " << *pos << '\n';
    } else {
        std::cout << "Символ не найден\n";
    }
}

Оператор *pos извлекает значение. Но делать это можно только после проверки. Если значения нет, разыменование приведёт к неопределённому поведению.

has_value() и value()

Вместо проверки через if (pos) можно явно вызвать has_value():

if (pos.has_value()) {
    std::cout << pos.value() << '\n';
}

Метод value() безопаснее оператора * в том смысле, что при отсутствии значения он бросит исключение std::bad_optional_access. Но это не значит, что им нужно злоупотреблять: лучше всё равно проверять optional заранее.

value_or(): значение по умолчанию

Если при отсутствии результата подходит значение по умолчанию, используйте value_or():

auto pos = findChar("hello", 'x');
std::size_t result = pos.value_or(std::string::npos);

if (result == std::string::npos) {
    std::cout << "Не найдено\n";
}

Это удобно для простых случаев, но не превращайте value_or() обратно в «магические числа» без необходимости. Часто лучше сохранить сам optional и явно обработать отсутствие значения.

Практический пример: чтение настройки

Допустим, программа получает порт сервера из конфигурации. Порт может отсутствовать или быть некорректным:

#include <optional>
#include <string>

std::optional<int> parsePort(const std::string& text) {
    if (text.empty()) return std::nullopt;

    int port = 0;
    for (char c : text) {
        if (c < '0' || c > '9') return std::nullopt;
        port = port * 10 + (c - '0');
    }

    if (port < 1 || port > 65535) return std::nullopt;
    return port;
}

Использование:

auto port = parsePort("8080");

if (!port) {
    std::cout << "Некорректный порт\n";
    return 1;
}

std::cout << "Сервер запущен на порту " << *port << '\n';

Такой код читается почти как обычный текст: «попробовали разобрать порт, если не получилось — обработали ошибку».

Когда использовать std::optional

  • Поиск: элемент может быть найден или не найден.
  • Парсинг: строка может успешно преобразоваться в число или оказаться неверной.
  • Необязательные параметры: у объекта может быть комментарий, дата, скидка и т.д.
  • Ленивая инициализация: значение создаётся позже, но хранится без динамической памяти.

Пример необязательного поля в структуре:

#include <optional>
#include <string>

struct User {
    std::string name;
    std::optional<std::string> email;
};

void printUser(const User& user) {
    std::cout << user.name << '\n';

    if (user.email) {
        std::cout << "Email: " << *user.email << '\n';
    }
}

Когда std::optional не подходит

std::optional не должен заменять обработку всех ошибок. Если нужно объяснить, почему операция не удалась, одного «значения нет» мало. Например, при открытии файла могут быть разные причины: нет прав, файл не найден, неверный формат. В таких случаях лучше использовать исключения, код ошибки или тип вроде std::expected из C++23.

Также не стоит использовать std::optional<bool> без крайней необходимости. У него уже три состояния: нет значения, true и false. Это может запутать читателя кода.

Частые ошибки новичков

  • Разыменовывать optional без проверки: *value допустимо только если значение есть.
  • Использовать optional там, где значение обязательно по логике программы.
  • Возвращать optional и всё равно использовать отдельный флаг успеха.
  • Путать пустую строку и отсутствие строки: "" и std::nullopt — разные вещи.

Рекомендации

Используйте std::optional, когда отсутствие значения — нормальная ожидаемая ситуация, а не авария. Называйте функции так, чтобы это было понятно: findUser(), parseNumber(), readConfigValue(). Проверяйте результат сразу после вызова и не откладывайте обработку «на потом».

Если вы только выстраиваете базу C++ и хотите уверенно разобраться не только с std::optional, но и с типами, функциями, ООП, STL и современными возможностями языка, посмотрите практический курс по C++ от основ до уверенной разработки — он хорошо подходит для последовательного обучения без хаоса.

Итог

std::optional в C++17 делает код честнее: тип функции сразу показывает, что результата может не быть. Это уменьшает количество скрытых договорённостей, магических значений и случайных ошибок. Главное правило простое: получил optional — сначала проверь, потом используй значение.

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

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

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

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

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

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

  1. Кнопка:

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

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

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

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

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

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