|
|
(12 intermediate revisions by 3 users not shown) |
Line 1: |
Line 1: |
− | {{title|try-block}}
| |
− | {{cpp/language/exceptions/navbar}}
| |
| | | |
− | Associates one or more exception handlers (catch-clauses) with a compound statement.
| |
− |
| |
− | ===Syntax===
| |
− | {{sdsc begin}}
| |
− | {{sdsc|1=
| |
− | {{ttb|try}} {{spar|compound-statement}} {{spar|handler-sequence}}
| |
− | }}
| |
− | {{sdsc end}}
| |
− |
| |
− | where {{spar|handler-sequence}} is a sequence of one or more {{spar|handler}}s, which have the following syntax:
| |
− |
| |
− | {{sdsc begin}}
| |
− | {{sdsc|num=1|1=
| |
− | {{ttb|catch}} {{ttb|(}} {{spar|attr}}{{mark optional}} {{spar|type-specifier-seq}} {{spar|declarator}} {{ttb|)}} {{spar|compound-statement}}
| |
− | }}
| |
− | {{sdsc|num=2|1=
| |
− | {{ttb|catch}} {{ttb|(}} {{spar|attr}}{{mark optional}} {{spar|type-specifier-seq}} {{spar|abstract-declarator}}{{mark optional}} {{ttb|)}} {{spar|compound-statement}}
| |
− | }}
| |
− | {{sdsc|num=3|1=
| |
− | {{ttb|catch}} {{ttb|(}} {{ttb|...}} {{ttb|)}} {{spar|compound-statement}}
| |
− | }}
| |
− | {{sdsc end}}
| |
− |
| |
− | {{par begin}}
| |
− | {{par|{{spar|compound-statement}}|brace-enclosed {{rlp|statements#Compound statements|sequence of statements}}}}
| |
− | {{par|{{spar|attr}}|{{mark since c++11}} any number of {{rlp|attributes}}, applies to the formal parameter}}
| |
− | {{par|{{spar|type-specifier-seq}}|part of a formal parameter declaration, same as in a {{rlp|function}} parameter list}}
| |
− | {{par|{{spar|declarator}}|part of a formal parameter declaration, same as in a {{rlp|function}} parameter list}}
| |
− | {{par|{{spar|abstract-declarator}}|part of an unnamed formal parameter declaration, same as in {{rlp|function}} parameter list}}
| |
− | {{par end}}
| |
− |
| |
− | @1@ Catch-clause that declares a named formal parameter
| |
− | {{source|try { /* */ } catch (const std::exception& e) { /* */ }
| |
− | }}
| |
− | @2@ Catch-clause that declares an unnamed parameter
| |
− | {{source|try { /* */ } catch (const std::exception&) { /* */ }
| |
− | }}
| |
− | @3@ Catch-all handler, which is activated for any exception
| |
− | {{source|try { /* */ } catch (...) { /* */ }
| |
− | }}
| |
− |
| |
− | ===Explanation===
| |
− | :{{small|See {{rlp|throw|throw exceptions}} for more information about throw-expressions}}
| |
− |
| |
− | A try-block is a {{rlp|statements|statement}}, and as such, can appear anywhere a statement can appear (that is, as one of the statements in a compound statement, including the function body compound statement). See {{rlp|function-try-block}} for the try blocks around function bodies. The following description applies to both try-blocks and {{rlp|function-try-block}}s.
| |
− |
| |
− | The formal parameter of the catch clause ({{spar|type-specifier-seq}} and {{spar|declarator}} or {{spar|type-specifier-seq}} and {{spar|abstract-declarator}}) determines which types of exceptions cause this catch clause to be entered. It cannot be an {{rlp|incomplete type}}, {{rlp|abstract class}} type,{{rev inl|since=c++11| {{rlp|reference|rvalue reference}} type,}} or pointer to incomplete type (except that pointers to (possibly {{rlp|cv}}-qualified) {{c|void}} are allowed). If the type of the formal parameter is array type or function type, it is treated as the corresponding pointer type (similar to a {{rlp|function|function declaration}}).
| |
− |
| |
− | When an exception is thrown by any statement in {{spar|compound-statement}}, the {{rlp|throw#The exception object|exception object}} of type {{tt|E}} is matched against the types of the formal parameters {{tt|T}} of each catch-clause in {{spar|handler-seq}}, in the order in which the catch clauses are listed. The exception is a match if any of the following is true:
| |
− | * {{tt|E}} and {{tt|T}} are the same type (ignoring top-level cv-qualifiers on {{tt|T}})
| |
− | * {{tt|T}} is an lvalue-reference to (possibly cv-qualified) {{tt|E}}
| |
− | * {{tt|T}} is an unambiguous public base class of {{tt|E}}
| |
− | * {{tt|T}} is a reference to an unambiguous public base class of {{tt|E}}
| |
− | * {{tt|T}} is (possibly cv-qualified) {{tt|U}} {{rev inl|since=c++14|or {{tt|const U&}}}}, and {{tt|U}} is a pointer {{rev inl|since=c++17|or pointer to member}} type, and {{tt|E}} is also a pointer {{rev inl|since=c++17|or pointer to member}} type that is implicitly convertible to {{tt|U}} by one or more of
| |
− | :* a standard {{rlp|implicit cast#Pointer conversions|pointer conversion}} other than one to a private, protected, or ambiguous base class
| |
− | :* a {{rlp|implicit cast#Qualification conversions|qualification conversion}}
| |
− | {{rev begin}}
| |
− | {{rev|since=c++17|
| |
− | :* a {{rlp|implicit cast#Function pointer conversions|function pointer conversion}}
| |
− | }}
| |
− | {{rev end}}
| |
− | * {{tt|T}} is a pointer or a pointer to member {{rev inl|since=c++14|or a reference to a const pointer}}, while {{tt|E}} is {{lc|std::nullptr_t}}.
| |
− |
| |
− | {{source|
| |
− | try
| |
− | {
| |
− | f();
| |
− | }
| |
− | catch (const std::overflow_error& e)
| |
− | {} // this executes if f() throws std::overflow_error (same type rule)
| |
− | catch (const std::runtime_error& e)
| |
− | {} // this executes if f() throws std::underflow_error (base class rule)
| |
− | catch (const std::exception& e)
| |
− | {} // this executes if f() throws std::logic_error (base class rule)
| |
− | catch (...)
| |
− | {} // this executes if f() throws std::string or int or any other unrelated type
| |
− | }}
| |
− |
| |
− | The catch-all clause {{c|catch (...)}} matches exceptions of any type. If present, it has to be the last catch clause in the {{spar|handler-seq}}. Catch-all block may be used to ensure that no uncaught exceptions can possibly escape from a function that offers {{rlp|exceptions|nothrow exception guarantee}}.
| |
− |
| |
− | If no matches are found after all catch-clauses were examined, the exception propagation continues to the containing try-block, as described in {{rlp|throw|throw-expression}}. If there are no containing try-blocks left, {{lc|std::terminate}} is executed (in this case, it is implementation-defined whether any stack unwinding occurs at all: throwing an uncaught exception is permitted to terminate the program without invoking any destructors).
| |
− |
| |
− | When entering a catch clause, if its formal parameter is a base class of the exception type, it is {{rlp|copy initialization|copy-initialized}} from the base class subobject of the exception object. Otherwise, it is copy-initialized from the exception object (this copy is subject to {{rlp|copy elision}}).
| |
− | {{source|1=
| |
− | try
| |
− | {
| |
− | std::string("abc").substr(10); // throws std::length_error
| |
− | }
| |
− | // catch (std::exception e) // copy-initialization from the std::exception base
| |
− | // {
| |
− | // std::cout << e.what(); // information from length_error is lost
| |
− | // }
| |
− | catch (const std::exception& e) // reference to the base of a polymorphic object
| |
− | {
| |
− | std::cout << e.what(); // information from length_error printed
| |
− | }
| |
− | }}
| |
− |
| |
− | If the parameter of the catch-clause is a reference type, any changes made to it are reflected in the exception object, and can be observed by another handler if the exception is rethrown with {{c|throw;}}. If the parameter is not a reference, any changes made to it are local and its lifetime ends when the handler exits.
| |
− |
| |
− | {{rev begin}}
| |
− | {{rev|since=c++11|
| |
− | Within a catch-clause, {{lc|std::current_exception}} can be used to capture the exception in an {{lc|std::exception_ptr}}, and {{lc|std::throw_with_nested}} may be used to build nested exceptions.}}
| |
− | {{rev end}}
| |
− |
| |
− | A {{rlp|goto}} or {{rlp|switch}} statement shall not be used to transfer control into a try block or into a handler.
| |
− |
| |
− | Other than by throwing or rethrowing the exception, the catch-clause after a regular try block (not {{rlp|function-try-block}}) may be exited with a {{rlp|return}}, {{rlp|continue}}, {{rlp|break}}, {{rlp|goto}}, or by reaching the end of its {{spar|compound-statement}}. In any case, this destroys the exception object (unless an instance of {{lc|std::exception_ptr}} exists that refers to it).
| |
− |
| |
− | ===Notes===
| |
− | The throw-expression {{c|throw NULL;}} is not guaranteed to be matched by a pointer catch clause, because the exception object type may be {{c|int}}, but {{c|throw nullptr;}} is assuredly matched by any pointer or pointer-to-member catch clause.
| |
− |
| |
− | If a catch-clause for a derived class is placed after the catch-clause for a base class, the derived catch-clause will never be executed:
| |
− | {{source|1=
| |
− | try
| |
− | {
| |
− | f();
| |
− | }
| |
− | catch (const std::exception& e)
| |
− | {} // will be executed if f() throws std::runtime_error
| |
− | catch (const std::runtime_error& e)
| |
− | {} // dead code!
| |
− | }}
| |
− |
| |
− | If {{rlp|goto}} is used to exit a try-block and if any of the destructors of block-scoped automatic variables that are executed by the {{tt|goto}} throw exceptions, those exceptions are caught by the try blocks in which the variables are defined:
| |
− | {{source|1=
| |
− | label:
| |
− | try
| |
− | {
| |
− | T1 t1;
| |
− | try
| |
− | {
| |
− | T2 t2;
| |
− | if (condition)
| |
− | goto label; // destroys t2, then destroys t1, then jumps to label
| |
− | }
| |
− | catch (...) {} // catches the exception from the destructor of t2
| |
− | }
| |
− | catch (...) {} // catches the exception from the destructor of t1
| |
− | }}
| |
− |
| |
− | ===Keywords===
| |
− | {{ltt|cpp/keyword/try}},
| |
− | {{ltt|cpp/keyword/catch}},
| |
− | {{ltt|cpp/keyword/throw}}
| |
− |
| |
− | ===Example===
| |
− | {{example
| |
− | |The following example demonstrates several usage cases of the {{tt|try-catch}} block
| |
− | |code=
| |
− | #include <iostream>
| |
− | #include <vector>
| |
− |
| |
− | int main()
| |
− | {
| |
− | try
| |
− | {
| |
− | std::cout << "Throwing an integer exception...\n";
| |
− | throw 42;
| |
− | }
| |
− | catch (int i)
| |
− | {
| |
− | std::cout << " the integer exception was caught, with value: " << i << '\n';
| |
− | }
| |
− |
| |
− | try
| |
− | {
| |
− | std::cout << "Creating a vector of size 5... \n";
| |
− | std::vector<int> v(5);
| |
− | std::cout << "Accessing the 11th element of the vector...\n";
| |
− | std::cout << v.at(10); // vector::at() throws std::out_of_range
| |
− | }
| |
− | catch (const std::exception& e) // caught by reference to base
| |
− | {
| |
− | std::cout << " a standard exception was caught, with message '"
| |
− | << e.what() << "'\n";
| |
− | }
| |
− | }
| |
− | |p=true
| |
− | |output=
| |
− | Throwing an integer exception...
| |
− | the integer exception was caught, with value: 42
| |
− | Creating a vector of size 5...
| |
− | Accessing the 11th element of the vector...
| |
− | a standard exception was caught, with message 'out_of_range'
| |
− | }}
| |
− |
| |
− | ===Defect reports===
| |
− | {{dr list begin}}
| |
− | {{dr list item|wg=cwg|dr=98|std=C++98|before=a switch statement can transfer control into a try block or into a handler|after=prohibited}}
| |
− | {{dr list item|wg=cwg|dr=210|std=C++98|before=the throw expression was matched against the catch clauses|after=the exception object is matched<br>against the catch clauses}}
| |
− | {{dr list item|wg=cwg|dr=1166|std=C++98|before=the behavior was unspecified when a catch clause whose<br>exception type is a reference to an abstract class type is matched|after=abstract class types are not<br>allowed for catch clauses}}
| |
− | {{dr list end}}
| |
− |
| |
− | {{langlinks|de|es|fr|it|ja|pt|ru|zh}}
| |