Исключения
Обработка исключений предоставляет способ передачи управления и информации из некоторой точки выполнения программы обработчику, связанному с точкой, ранее пройденной при выполнении (иными словами, обработка исключений передаёт управление вверх по стеку вызовов).
Вычисление выражения throw вызывает исключение. Исключения также могут вызываться в других контекстах.
Чтобы исключение было перехвачено, выражение throw должно находиться внутри блока try, а блок try должен содержать обработчик, соответствующий типу объекта исключения.
При объявлении функции могут указываться следующие спецификации, ограничивающие типы исключений, которые может вызвать функция:
| (до C++17) |
| (начиная с C++11) |
Ошибки, возникающие при обработке исключений, обрабатываются с помощью std::terminate и std::unexpected(до C++17).
Использование
Хотя выражение throw можно использовать для передачи управления произвольному блоку кода выше по стеку выполнения по произвольным причинам (аналогично std::longjmp), его предполагаемое назначение — обработка ошибок.
Обработка ошибок
Исключения используются для сигнализации об ошибках из функций, причём под «ошибками» обычно понимаются только следующие ситуации[1][2][3]:
- Невыполнение постусловий, например невозможность создать корректный объект возвращаемого значения.
- Невыполнение предусловий другой функции, которую необходимо вызвать.
- (для непубличных функций-членов) Невозможность установить или восстановить инвариант класса.
В частности, отсюда следует, что о сбоях конструкторов (см. также RAII) и большинства операторов следует сообщать посредством исключений.
Кроме того, так называемые функции с широким контрактом используют исключения для обозначения недопустимых входных данных. Например, у std::basic_string::at нет предусловий, но он вызывает исключение, чтобы указать на выход индекса за границы.
Безопасность исключений
После того как функция сообщила об ошибке, могут предоставляться дополнительные гарантии относительно состояния программы. Обычно выделяют следующие четыре уровня гарантий безопасности исключений[4][5][6], каждая из которых строже предыдущей:
-
Гарантия отсутствия исключений (или безотказности) — функция никогда не вызывает исключений. Гарантия отсутствия исключений (ошибки сообщаются другими способами или скрываются) ожидается от деструкторов и других функций, которые могут вызываться при раскрутке стека. Деструкторы по умолчанию являются
noexcept.(начиная с C++11) Гарантия безотказности (функция всегда завершается успешно) ожидается от операций обмена, перемещающих конструкторов и других функций, используемых теми, которые предоставляют строгую гарантию безопасности исключений. -
Строгая гарантия безопасности исключений — если функция вызывает исключение, состояние программы откатывается к состоянию, существовавшему непосредственно перед вызовом функции (например,
std::vector::push_back). - Базовая гарантия безопасности исключений — если функция вызывает исключение, программа остаётся в корректном состоянии. Утечки ресурсов отсутствуют, а инварианты всех объектов сохраняются.
- Отсутствие гарантии безопасности исключений — если функция вызывает исключение, программа может оказаться в некорректном состоянии: возможны утечки ресурсов, повреждение памяти или другие ошибки, нарушающие инварианты.
Кроме того, обобщённые компоненты могут предоставлять гарантию нейтральности к исключениям: если исключение возникает в параметре шаблона (например, в функциональном объекте Compare из std::sort или в конструкторе T в std::make_shared), оно передаётся вызывающему коду без изменений.
Объекты исключений
В качестве объектов исключений можно выбрасывать объекты любых полных типов и указатели cv на void, однако все функции стандартной библиотеки выбрасывают безымянные объекты по значению, а типы этих объектов прямо или косвенно наследуются от std::exception. Пользовательские исключения обычно следуют этому шаблону.[7][8][9]
Чтобы избежать ненужного копирования объекта исключения и срезки объекта, обработчикам рекомендуется перехватывать исключения по ссылке.[10][11][12][13]
Примечания
| Макрос проверки поддержки функции | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_constexpr_exceptions | 202411L | (C++26) | исключения constexpr |
Внешние ссылки
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/exceptions