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_alloc
, bad_cast
, bad_typeid
, and 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 const
.
-
bad_alloc
: thrown whenoperator new
can’t satisfy a memory request (MECpp item 8);bad_cast
: thrown when adynamic_cast
to a reference fails (MECpp item 2);bad_typeid
: thrown whentypeid
is applied to a dereferenced null pointer; andbad_exception
: available for unexpected exceptions (MECpp item 14) ↩︎