Home » C++ » Using `throw;` on a modified exception

Using `throw;` on a modified exception

Posted by: admin November 30, 2017 Leave a comment

Questions:

I have a function foo that can throw a bar exception.

In another function I call foo but I have the ability to add some more detail to the bar exception if thrown. (I’d rather not pass such information as a parameter to foo as it doesn’t really belong there due to the generic nature of that function.)

So I do this in the caller:

try {
    foo();
} catch (bar& ex){
    ex.addSomeMoreInformation(...);
    throw;
}

Will throw re-throw the modified exception or do I need to use throw ex;? The latter would presumably take a value copy so I’d rather not do that. Would throw take a value copy too? I suspect it wouldn’t.

(I’m aware I could verify but I’m concerned about stumbling on an unspecified or undefined construct so would like to know for sure).

Answers:

C++11 §15.1/8:

A throw-expression with no operand rethrows the currently handled exception (15.3). The exception is
reactivated with the existing temporary; no new temporary exception object is created.

Questions:
Answers:

Actually, the standard is very precise here. [except.handle]/17:

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
.

And [except.throw]/8:

A throw-expression with no operand rethrows the currently handled
exception (15.3).

Questions:
Answers:

In this case you should use throw to get the desired behavior…i.e throw would throw the modified exception as the exception was caught by reference.

Let me try to make difference between these throw explicit through examples:-

class exception
{
};

class MyException : public exception
{
};

void func()
{
  try
  {
    throw MyException();
  }
  catch( exception& e )
  {
    //do some modification.
    throw;                    //Statement_1
    throw e;                  //Statement_2
   }
}

Statment_1:-

What throw does is it just re-throws what the current exception is i.e it doesn’t make further copies ( as was made when exception was thrown initially). So if you make any changes to the caught exception here…it would also be there in the caller routine.

Statement_2:-

This is throwing the “exception” which was originally caught as MyException i.e it would make the copy again. So, just forget about changes you made it won’t even passes or*ginal exception to the caller. It throws “exception” to the caller routine.

Hope I am clear ( and RIGHT ON TRACK OF C++ STANDARD )enough…

Questions:
Answers:

throw (without an exception object) will rethrow the current exception. (must be inside catch block, otherwise std::terminate is called). Because you changed the reference of current exception object, you don’t need to explicilty throw the object and throw re-throw the modified exception and no new temporary object is created.

Questions:
Answers:

according to this,throwing exceptions in c++ can be done in two ways:

  1. throw expression: First, copy-initializes the exception object from expression (this may call the move constructor for rvalue expression, and the copy/move may be subject to copy elision), then transfers control to the exception handler with the matching type whose compound statement or member initializer list was most recently entered and not exited by this thread of execution.
  2. throw: Rethrows the currently handled exception. Abandons the execution of the current catch block and passes control to the next matching exception handler (but not to another catch clause after the same try block: its compound-statement is considered to have been ‘exited’), reusing the existing exception object: no new objects are made. This form is only allowed when an exception is presently being handled (it calls std::terminate if used otherwise). The catch clause associated with a function-try-block must exit via rethrowing if used on a constructor.

So to underline my answer, throw should be fine in your case.