Namespaces
Variants
Views
Actions

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

From cppreference.com
< cpp‎ | language
m (fmt.)
(Blanked the page (can be removed). The content is now in cpp/language/try and cpp/language/catch.)
 
(One intermediate revision by one user 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 optional|attr}} {{spar|type-specifier-seq}} {{spar|declarator}} {{ttb|)}} {{spar|compound-statement}}
 
}}
 
{{sdsc|num=2|1=
 
{{ttb|catch}} {{ttb|(}} {{spar optional|attr}} {{spar|type-specifier-seq}} {{spar optional|abstract-declarator}} {{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}} or {{c|const U&}}, and {{tt|U}} is a pointer or pointer to member type, and {{tt|E}} is also a pointer or pointer to member type that is implicitly convertible to {{tt|U}} by one or more of
 
:* a standard {{rlp|implicit conversion#Pointer conversions|pointer conversion}} other than one to a private, protected, or ambiguous base class
 
:* a {{rlp|implicit conversion#Qualification conversions|qualification conversion}}
 
{{rrev|since=c++17|
 
:* a {{rlp|implicit conversion#Function pointer conversions|function pointer conversion}}
 
}}
 
{{rrev|since=c++11|
 
* {{tt|T}} is (possibly cv-qualified) {{tt|U}} or {{c|const U&}}, where {{tt|U}} is a pointer or a pointer to member type, and {{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.
 
 
{{rrev|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.
 
}}
 
 
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
 
}}
 
 
Many implementations overly extend the resolution of {{wg21|cwg388}} to handlers of reference to non-const pointer types:
 
{{source|1=
 
int i;
 
try
 
{
 
    try
 
    {
 
        throw static_cast<float*>(nullptr);
 
    }
 
    catch (void*& pv)
 
    {
 
        pv = &i;
 
        throw;
 
    }
 
}
 
catch (const float* pf)
 
{
 
    assert(pf == nullptr); // should pass, but fails on MSVC and Clang
 
}
 
}}
 
 
===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<br>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=388|std=C++98|before=an exception of pointer or pointer to member type could not<br>be matched by a const reference to a different type|after=made matchable when convertible}}
 
{{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 item|wg=cwg|dr=1769|std=C++98|before=when the type of the exception declared in the catch-clause is a<br>base of the type of the exception object, a converting constructor<br>might be used for the initialization of the catch-clause parameter|after=the parameter is copy-initialized<br>from the corresponding base class<br>subobject of the exception object}}
 
{{dr list item|wg=cwg|dr=2093|std=C++98|before=an exception object of pointer to object type could not match a<br>handler of pointer to object type through qualification conversion|after=allowed}}
 
{{dr list end}}
 
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 

Latest revision as of 22:46, 6 June 2024