Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does catching a const int& by an int& work?

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&?

like image 471
sank Avatar asked Jan 22 '19 05:01

sank


2 Answers

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 [...]

like image 90
Swordfish Avatar answered Oct 05 '22 02:10

Swordfish


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.

like image 43
David Schwartz Avatar answered Oct 05 '22 01:10

David Schwartz