From [except.throw]/2:
When an exception is thrown, control is transferred to the nearest handler with a matching type ([except.handle]); “nearest” means the handler for which the compound-statement or ctor-initializer following the try keyword was most recently entered by the thread of control and not yet exited.
First of all, I really can't understand this quote properly, and how it is applied in a particular code. So any understandable explanations, with simple words, will be very appreciated.
Consider this two code snippets:
/ * code A */
try
{
throw 1;
}
catch (int) // nearest handler for throwing 1. #first_handler
{
}
-----------------------------------------------
/* code B */
try
{
try
{
throw 1;
}
catch (int) // nearest handler for throwing 1. #second_handler
{
throw 2;
}
}
catch (int) // nearest handler for throwing 2
{
}
Because I cannot understand the above quote, I don't know how I can determine the nearest handler, and I cannot apply [except.throw]/2
in the above examples. My question is just how does [except.throw]/2
is applied in the above code? or in other words, why first_handler
and second_handler
are nearest handlers?
CodePudding user response:
Exceptions travel upwards, hence you can look for the next try
then see if it has a matching catch
, if not continue. For example
try { // 4
try { // 2
throw "foo"; // 1
} catch(int) { } // 3
} catch(...) { // 5
std::cout << "hello exception";
}
When the excpetion is thrown in 1
then control flow goes backwards and the first try
is the one in 2
. It does not have a matching catch
, it only catches int
(3
). Hence, you look further upwards to find the try
in 4
. It has a catch
that catches any exception 5
and that is the "nearest".
[...] "“nearest” means the handler for which the compound-statement following the try keyword was most recently entered by the thread of control and not yet exited." What that's "not yet exited"? I can't get the bold part.
Thats the second example:
try // try 2
{
try // try 1
{
throw 1;
} // <---- the try block is exited here
catch (int) // catch 1
{
throw 2;
}
}
catch (int) // catch 2
{
}
throw 2
will be handled by catch 2
because thats the nearest handler. The nearest handler is not catch 1
because that belongs to try 1
. And when throw 2
is executed then the try 1
block is already exited.