Namespaces
Variants

Exceptions

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Обработка исключений предоставляет способ передачи управления и информации из некоторой точки выполнения программы обработчику, связанному с точкой, ранее пройденной выполнением (другими словами, обработка исключений передает управление вверх по стеку вызовов).

Вычисление throw выражения приведет к выбросу исключения. Исключения также могут быть выброшены в других контекстах .

Чтобы исключение было перехвачено, выражение throw должно находиться внутри try блока , и try блок должен содержать обработчик , соответствующий типу объекта исключения.

При объявлении функции могут быть указаны следующие спецификации для ограничения типов исключений, которые функция может выбрасывать:

(до C++17)
(начиная с C++11)

Ошибки, возникающие во время обработки исключений, обрабатываются с помощью std::terminate и std::unexpected (до C++17) .

Содержание

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

Хотя throw выражение может использоваться для передачи управления в произвольный блок кода вверх по стеку выполнения по произвольным причинам (аналогично std::longjmp ), его предназначение — обработка ошибок.

Обработка ошибок

Выброс исключения используется для сигнализации об ошибках из функций, где «ошибки» обычно ограничиваются только следующим [1] [2] [3] :

  1. Нарушения постусловий, такие как невозможность создать корректный объект возвращаемого значения.
  2. Нарушения предусловий другой функции, которая должна быть вызвана.
  3. (для не-private функций-членов) Нарушения (пере)установки инварианта класса.

В частности, это означает, что неудачи конструкторов (см. также RAII ) и большинства операторов должны сообщаться путем выбрасывания исключений.

Кроме того, так называемые функции с широким контрактом используют исключения для обозначения недопустимых входных данных, например, std::basic_string::at не имеет предусловий, но генерирует исключение для обозначения выхода индекса за пределы диапазона.

Гарантия безопасности исключений

После того как функция сообщает об ошибке, могут быть предоставлены дополнительные гарантии относительно состояния программы. Обычно выделяют следующие четыре уровня гарантии исключений [4] [5] [6] , которые являются строгими надмножествами друг друга:

  1. Гарантия исключений nothrow (или nofail) — функция никогда не выбрасывает исключения. Nothrow (ошибки сообщаются другими способами или скрываются) ожидается от деструкторов и других функций, которые могут быть вызваны во время раскрутки стека. Деструкторы по умолчанию являются noexcept . (начиная с C++11) Nofail (функция всегда завершается успешно) ожидается от swap-функций, конструкторов перемещения и других функций, используемых теми, кто предоставляет строгую гарантию исключений.
  2. Строгая гарантия исключений — Если функция выбрасывает исключение, состояние программы откатывается к состоянию непосредственно перед вызовом функции (например, std::vector::push_back ).
  3. Базовая гарантия исключений — Если функция выбрасывает исключение, программа остается в допустимом состоянии. Утечки ресурсов не происходит, и инварианты всех объектов сохраняются.
  4. Отсутствие гарантии исключений — Если функция выбрасывает исключение, программа может оказаться в недопустимом состоянии: возможны утечки ресурсов, повреждение памяти или другие ошибки, нарушающие инварианты.

Кроме того, универсальные компоненты могут предоставлять гарантию нейтральности к исключениям : если исключение выбрасывается параметром шаблона (например, функциональным объектом 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 исключения

Внешние ссылки

  1. H. Sutter (2004) "Когда и как использовать исключения" в Dr. Dobb's
  2. H. Sutter, A. Alexandrescu (2004), "C++ Coding Standards", Пункт 70
  3. C++ Core Guidelines I.10: Используйте исключения для сигнализации о неудаче выполнения требуемой задачи
  4. B. Stroustrup (2000), "The C++ Programming Language" Приложение E
  5. H. Sutter (2000) "Exceptional C++"
  6. D. Abrahams (2001) "Безопасность исключений в обобщенных компонентах"
  7. D. Abrahams (2001) "Обработка ошибок и исключений"
  8. isocpp.org Super-FAQ "Что следует выбрасывать?"
  9. C++ Core Guidelines E.14: Используйте специально разработанные пользовательские типы в качестве исключений (не встроенные типы)
  10. C++ Core Guidelines E.15: Выбрасывайте по значению, перехватывайте исключения из иерархии по ссылке
  11. S. Meyers (1996) "More Effective C++" Пункт 13
  12. isocpp.org Super-FAQ "Что следует перехватывать?"
  13. H. Sutter, A. Alexandrescu (2004) "C++ Coding Standards" Пункт 73