If catching by reference, we sidestep the questions about object deletion, avoid slicing exception objects, retain the ability to catch standard exceptions, and limit the number of times exception objects being copied.
Catch by pointer
In order to catch by pointer, programmers need to define exception objects in a way that guarantees the objects exist after control leaves the
throw site. Global and static objects work fine, but it’s easy for programmers to forget the constraint:
An alternative is to throw a pointer to a new heap object:
This design will make a hard time for authors of
catch clauses: to delete or not to delete the pointer they receive? In the
catch site, we can’t tell if an exception object is allocated on the heap or defined as a global (or static) object.
Furthermore, catch-by-pointer runs contrary to the convention of the language: the four standard exception1 -
bad_exception are all objects, rather than pointers to objefts, so we have to catch them by value or by reference.
Catch by value
Catch-by-value requires exception objects be copied twice each time they thrown (MECpp item 12), and it also has slicing problem: derived class exception objects caught as base class exceptions have their derivedness “sliced off” : they lack derived class data members, and resolve to base class virtual functions (the same behavior as when an object is passed to a function by value)
Catch by reference
Catch-by-reference suffers from none of the problems:
- Unlike catch-by-pointer, the question of object deletion fails to arise, and there’s no difficulty in catching the standard exception types
- Unlike catch-by-value, there is no slicing problem, and exception objects are copied only once.
Of course, if there’s no need to change the exception object in the
catch site, we’d catch not just reference, but by reference to
bad_alloc: thrown when
operator newcan’t satisfy a memory request (MECpp item 8);
bad_cast: thrown when a
dynamic_castto a reference fails (MECpp item 2);
bad_typeid: thrown when
typeidis applied to a dereferenced null pointer; and
bad_exception: available for unexpected exceptions (MECpp item 14) ↩︎