C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 17:
[17.14] But MFC seems to encourage the use of catch-by-pointer; should I do the same?

Depends. If you're using MFC and catching one of their exceptions, by all means, do it their way. Same goes for any framework: when in Rome, do as the Romans. Don't try to force a framework into your way of thinking, even if "your" way of thinking is "better." If you decide to use a framework, embrace its way of thinking — use the idioms that its authors expected you to use.

But if you're creating your own framework and/or a piece of the system that does not directly depend on MFC, then don't catch by pointer just because MFC does it that way. When you're not in Rome, you don't necessarily do as the Romans. In this case, you should not. Libraries like MFC predated the standardization of exception handling in the C++ language, and some of these libraries use a backwards-compatible form of exception handling that requires (or at least encourages) you to catch by pointer.

The problem with catching by pointer is that it's not clear who (if anyone) is responsible for deleting the pointed-to object. For example, consider the following:

MyException x;

void f()
{
  MyException y;

  try {
    switch ((rand() >> 8) % 3) {  // the ">> 8" (typically) improves the period of the lowest 2 bits
      case 0: throw new MyException;
      case 1: throw &x;
      case 2: throw &y;
    }
  }
  catch (MyException* p) {
    ...         should we delete p here or not???!?
  }
}
There are three basic problems here:
  1. It might be tough to decide whether to delete p within the catch clause. For example, if object x is inaccessible to the scope of the catch clause, such as when it's buried in the private part of some class or is static within some other compilation unit, it might be tough to figure out what to do.
  2. If you solve the first problem by consistently using new in the throw (and therefore consistently using delete in the catch), then exceptions always use the heap which can cause problems when the exception was thrown because the system was running low on memory.
  3. If you solve the first problem by consistently not using new in the throw (and therefore consistently not using delete in the catch), then you probably won't be able to allocate your exception objects as locals (since then they might get destructed too early), in which case you'll have to worry about thread-safety, locks, semaphores, etc. (static objects are not intrinsically thread-safe).

This isn't to say it's not possible to work through these issues. The point is simply this: if you catch by reference rather than by pointer, life is easier. Why make life hard when you don't have to?

The moral: avoid throwing pointer expressions, and avoid catching by pointer, unless you're using an existing library that "wants" you to do so.