Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/try catch"

From cppreference.com
< cpp‎ | language
m (update anchor link since "compound statement" was renamed)
(Blanked the page (can be removed). The content is now in cpp/language/try and cpp/language/catch.)
 
(27 intermediate revisions by 8 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 c++11}} | optional list 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|reference|rvalue reference type}}, {{rlp|abstract class}}, {{rlp|incomplete 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 of type {{tt|E}} is thrown by any statement in {{spar|compound-statement}}, it 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 a (possibly cv-qualified) pointer {{rev inl|since=c++14|or a reference to a const pointer}}, and {{tt|E}} is also a pointer, which is implicitly convertible to T by one or more of
 
:* a standard {{rlp|implicit_cast|pointer conversion}}
 
:* a {{rlp|implicit_cast|qualification conversion}}
 
{{rev begin}}
 
{{rev|since=c++17|
 
:* a {{rlp|implicit_cast|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(...)}} matched 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 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}}
 
 
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 matched by a pointer catch clause, because the exception object type is {{c|int}}, but {{c|throw nullptr;}} is 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";
 
    }
 
 
}
 
| 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'
 
}}
 
 
[[de:cpp/language/try catch]]
 
[[es:cpp/language/try catch]]
 
[[fr:cpp/language/try catch]]
 
[[it:cpp/language/try catch]]
 
[[ja:cpp/language/try catch]]
 
[[pt:cpp/language/try catch]]
 
[[ru:cpp/language/try catch]]
 
[[zh:cpp/language/try catch]]
 

Latest revision as of 22:46, 6 June 2024