[except.throw] (original) (raw)
14 Exception handling [except]
14.2 Throwing an exception [except.throw]
Throwing an exception transfers control to a handler.
An object is passed and the type of that object determines which handlers can catch it.
[Example 1:
throw "Help!";can be caught by ahandlerofconst char*type:try { } catch(const char* p) { } andclass Overflow { public: Overflow(char,double,double);};void f(double x) { throw Overflow('+',x,3.45e107);} can be caught by a handler for exceptions of typeOverflow:try { f(1.2);} catch(Overflow& oo) { }
— _end example_]
When an exception is thrown, control is transferred to the nearest handler with a matching type ([except.handle]); “nearest” means the handler for which thecompound-statement orctor-initializerfollowing thetrykeyword was most recently entered by the thread of control and not yet exited.
An lvalue denoting the temporary is used to initialize the variable declared in the matchinghandler ([except.handle]).
If the type of the exception object would be an incomplete type, an abstract class type ([class.abstract]), or a pointer to an incomplete type other than cv voidthe program is ill-formed.
The memory for the exception object is allocated in an unspecified way, except as noted in [basic.stc.dynamic.allocation].
If a handler exits by rethrowing, control is passed to another handler for the same exception object.
The points of potential destruction for the exception object are:
- when an active handler for the exception exits by any means other than rethrowing, immediately after the destruction of the object (if any) declared in the exception-declaration in the handler;
- when an object of type std::exception_ptrthat refers to the exception object is destroyed, before the destructor of std::exception_ptr returns.
Among all points of potential destruction for the exception object, there is an unspecified last one where the exception object is destroyed.
[Note 2:
No other thread synchronization is implied in exception handling.
— _end note_]
The implementation may then deallocate the memory for the exception object; any such deallocation is done in an unspecified way.
[Note 3:
A thrown exception does not propagate to other threads unless caught, stored, and rethrown using appropriate library functions; see [propagation] and [futures].
— _end note_]
When the thrown object is a class object, the constructor selected for the copy-initialization as well as the constructor selected for a copy-initialization considering the thrown object as an lvalue shall be non-deleted and accessible, even if the copy/move operation is elided ([class.copy.elision]).
The destructor is potentially invoked ([class.dtor]).
An exception is considered caught when a handler for that exception becomes active.
[Note 4:
An exception can have active handlers and still be considered uncaught if it is rethrown.
— _end note_]
If the exception handling mechanism handling an uncaught exceptiondirectly invokes a function that exits via an exception, the function std::terminate is called.
[Example 2: struct C { C() { } C(const C&) { if (std::uncaught_exceptions()) { throw 0; } } };int main() { try { throw C(); } catch(C) { } } — _end example_]
[Note 5:
If a destructor directly invoked by stack unwinding exits via an exception,std::terminate is invoked.
— _end note_]