throw expression
Signals an erroneous condition and executes an error handler.
Contents |
[edit] Syntax
throw expression
|
(1) | ||||||||
throw
|
(2) | ||||||||
[edit] Explanation
- See try-catch block for more information about try and catch (exception handler) blocks
See std::terminate and std::unexpected for the handling of errors that arise during exception handling.
[edit] The exception object
The exception object is a temporary object in unspecified storage that is constructed by the throw
expression.
The type of the exception object is the static type of expression with top-level cv-qualifiers removed. Array and function types are adjusted to pointer and pointer to function types, respectively. If the type of the exception object would be an incomplete type or pointer to incomplete type other than pointer to (cv-qualified) void, the throw-expression is a compile-time error. If the type of expression is a class type, its copy/move constructor and destructor must be accessible even if copy elision takes place.
Unlike other temporary objects, the exception object is considered to be an lvalue argument when initializing the catch clause parameters, so it can be caught by lvalue reference, modified, and rethrown.
The exception object persists until the last catch clause exits other than by rethrowing (in which case it is destroyed immediately after the destruction of the catch clause's parameter), or until the last std::exception_ptr that references this object is destroyed (in which case the exception object is destroyed just before the destructor of std::exception_ptr returns.
[edit] Stack unwinding
Once the exception object is constructed, the control flow works backwards (up the call stack) until it reaches the start of a try block, at which point the parameters of all associated catch
blocks are compared, in order of appearance, with the type of the exception object to find a match (see try-catch for details on this process). If no match is found, the control flow continues to unwind the stack until the next try
block, and so on. If a match is found, the control flow jumps to the matching catch
block.
As the control flow moves up the call stack, destructors are invoked for all objects with automatic storage duration constructed since the corresponding try-block was entered, in reverse order of completion of their constructors.
If an exception is thrown from a constructor or (rare) from a destructor of an object (regardless of the object's storage duration), destructors are called for all fully-constructed non-static non-variant members and base classes, in reverse order of completion of their constructors.
If a delegating constructor exits with an exception after the non-delegating constructor successfully completed, the destructor for this object is called. | (since C++11) |
If the exception is thrown from a constructor that is invoked by a new-expression, the matching deallocation function is called, if available.
This process is called stack unwinding.
If any function that is called during stack unwinding, after initialization of the exception object and before the start of the exception handler, exits with an exception, std::terminate is called. Such functions include destructors of objects with automatic storage duration whose scopes are exited, and the copy constructor of the exception object that is called (if not elided) to initialize catch-by-value arguments.
[edit] Notes
When rethrowing exceptions, the second form must be used to avoid object slicing in the (typical) case where exception objects use inheritance:
try { std::string("abc").substr(10); // throws std::length_error } catch(const std::exception& e) { std::cout << e.what() << '\n'; // throw e; // copy-initializes a new exception object of type std::exception throw; // rethrows the exception object of type std::length_error }
The throw-expression is classified as prvalue expression of type void. Like any other expression, it may be a sub-expression in another expression, most commonly in the conditional operator:
double f(double d) { return d > 1e7 ? throw std::overflow_error("too big") : d; } int main() { try { std::cout << f(1e10) << '\n'; } catch (const std::overflow_error& e) { std::cout << e.what() << '\n'; } }
[edit] Keywords
[edit] Example
This section is incomplete Reason: no example |