[C++11: 15.1/3]:
A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of T” or “function returning T” to “pointer to T” or “pointer to function returning T”, respectively. The temporary is an lvalue and is used to initialize the variable named in the matching handler (15.3). If the type of the exception object would be an incomplete type or a pointer to an incomplete type other than (possibly cv-qualified) void the program is ill-formed. Except for these restrictions and the restrictions on type matching mentioned in 15.3, the operand ofthrow
is treated exactly as a function argument in a call (5.2.2) or the operand of a return statement.
In short, you're slicing it, despite the exception handler having accepted a reference.
Re-throwing should be accomplished by writing simply throw
, on its own. This is exactly its purpose:
[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. [..]
So:
throw e; // no
throw; // yes