Создание исключения передает управление обработчику. [ Note: Исключение может быть выброшено из одного из следующих контекстов: throw-expressions, allocation functions, dynamic_cast, typeid, new-expressions, и стандартные библиотечные функции ([structure.specifications]). ] Объект передается, и тип этого объекта определяет, какие обработчики могут его перехватить. [ — end note Example:
throw "Help!";
может быть захвачено handler из const char* типа:
try { // ... } catch(const char* p) { // handle character string exceptions here }
а также
class Overflow { public: Overflow(char,double,double); }; void f(double x) { throw Overflow('+',x,3.45e107); }
может быть перехвачен обработчиком исключений типа Overflow:
try {
f(1.2);
} catch(Overflow& oo) {
// handle exceptions of type Overflow here
}
— end example ]
Когда генерируется исключение, управление передается ближайшему обработчику с подходящим типом ([except.handle]); «Ближайший» означает обработчик, для которого ключевое слово compound-statementили ctor-initializer следующее за tryключевым словом было самым последним введено потоком управления и еще не завершено.
Создание исключения инициализирует копирование-инициализацию ([dcl.init], [class.copy]) временного объекта, называемого exception object. Значение lvalue, обозначающее временное, используется для инициализации переменной, объявленной в match handler([except.handle]). Если тип объекта исключения будет неполным типом или указатель на неполный тип, отличный cv void от программы, сформирован неправильно.
Память для объекта исключения распределяется неопределенным образом, за исключением случаев, указанных в [basic.stc.dynamic.allocation]. Если обработчик завершает работу путем повторной генерации, управление передается другому обработчику для того же объекта исключения. Точки потенциального разрушения объекта исключения:
когда активный обработчик исключения завершает работу любым способом, кроме повторной генерации, сразу после уничтожения объекта (если есть), объявленного exception-declarationв обработчике;
когда объект типа, std::exception_ptr который ссылается на объект исключения, уничтожается до того, как деструктор std::exception_ptr возвращает.
Среди всех точек потенциального разрушения для объекта исключения есть неуказанная последняя, в которой уничтожается объект исключения. Все остальные пункты, happen before которые последний. [ Note: Никакая другая синхронизация потоков не подразумевается при обработке исключений. ] Затем реализация может освободить память для объекта исключения; любое такое освобождение выполняется неуказанным образом. [ Выброшенное исключение не распространяется на другие потоки, если оно не будет поймано, сохранено и повторно создано с использованием соответствующих библиотечных функций; видеть и . ] — end note Note: [propagation] [futures] — end note
Когда брошенный объект является объектом класса, конструктор, выбранный для инициализации копирования, а также конструктор, выбранный для инициализации копирования, учитывая, что брошенный объект является lvalue, не должны быть удалены и доступны, даже если операция копирования / перемещения есть elided. Деструктор есть potentially invoked.
Исключение считается пойманным, когда его обработчик становится active. [ Note: Исключение может иметь активные обработчики и по-прежнему считаться неперехваченным, если оно генерируется повторно. ] — end note
Если механизм обработки исключений, обрабатывающий объект, uncaught exception напрямую вызывает функцию, которая завершается через исключение, std::terminate вызывается. [ Example:
struct C { C() { } C(const C&) { if (std::uncaught_exceptions()) { throw 0; // throw during copy to handler's exception-declaration object ([except.handle]) } } }; int main() { try { throw C(); // calls std::terminate() if construction of the handler's // exception-declaration object is not elided } catch(C) { } }
— end example ] [ Note: Следовательно, деструкторы обычно должны перехватывать исключения и не позволять им распространяться. ] — end note