In the following code, I throw an int, catch it as const int&, re-throw it and catch it again catch it as an int&.
#include <iostream>
int main()
{
try
{
try
{
int x = 1;
throw x;
}
catch(const int& e)
{
std::cout << "Inner catch" << std::endl;
throw;
}
}
catch(int & e1)
{
std::cout << "Outer catch" << std::endl;
}
return 0;
}
The above program compiles successfully and prints
Inner catch
Outer catch
On the other hand the following program in which I am trying to initialize an int& by a const int& wouldn't even compile.
#include <iostream>
int main()
{
int x = 0;
const int& y = x;
int& z = y
return 0;
}
I get the following error as expected
binding ‘const int’ to reference of type ‘int&’ discards qualifiers
int& z = y
Why am I allowed to catch an const int& as an int& but not able to assign cons int& to int&?
except.handle/3:
A handler is a match for an exception object of type E if
(3.1) – The handler is of type cv T or cv T& and E and T are the same type (ignoring the top-level cv-qualifiers), or [...]
A throw is always by value. You can catch it with a const
or with a reference if you want, but the object thrown is always a copy. So it's perfectly safe to catch it with a non-const
and to modify it. You can test this by printing the address of an int
, then throw it, catch it by reference, and print the address of the reference. You'll see it's a different address.
You can even do this:
try
{
throw 3;
}
catch (int& q)
{
q = 4;
}
The value of the thrown object with the value 3
is modified because q
binds to a new int
initialized with the thrown value. You always throw a value.
The exception is just throw;
, which re-throws the existing object. It has to be this way because otherwise, it would be impossible to sanely manage the lifetime of thrown objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With