21

Does the standard have anything to say about an exception that is caught by reference and what happens to attempts to modify it?

Consider the following code:

class my_exception: public std::logic_error
{
public:
    std::vector<std::string> callstack;
};

void MyFunc()
{
    try
    {
        SomethingThatThrows();
    }
    catch (my_exception & e)
    {
        e.callstack.push_back("MyFunc");
        throw;
    }
}

This is a contrived example, I'm not actually attempting something like this. I was just curious what would happen, based on the suggestion in another thread that exceptions should be caught by const reference.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 1
    boost::exception has some neat tools for this. – Tom Kerr Dec 12 '11 at 21:37
  • 1
    push_back can throw. Copy constructor of string can throw. Today I'd prefer a std::array what_msg inside exception. So that you can implement virtual what easily. – Muxecoid Oct 29 '13 at 08:00

2 Answers2

21

The exception will change.

§15.3[except.handle]/17:

When the handler declares a non-constant object, any changes to that object will not affect the temporary object that was initialized by execution of the throw-expression.

When the handler declares a reference to a non-constant object, any changes to the referenced object are changes to the temporary object initialized when the throw-expression was executed and will have effect should that object be rethrown.

So if my_exception is caught outside of MyFunc, we'll see the "MyFunc" entry in the callstack (e.g. http://ideone.com/5ytqN)

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
10

Yes, you can do this.

When you rethrow the current exception using throw;, no copies are made: the original temporary exception object is rethrown. Thus, any changes you make to that object in the handler will be present in the exception object when you next catch it.

James McNellis
  • 348,265
  • 75
  • 913
  • 977