Back to Item 8: Understand the different meanings of new and delete
Continue to Item 9: Use destructors to prevent resource leaks.

Exceptions

The addition of exceptions to C++ changes things. Profoundly. Radically. Possibly uncomfortably. The use of raw, unadorned pointers, for example, becomes risky. Opportunities for resource leaks increase in number. It becomes more difficult to write constructors and destructors that behave the way we want them to. Special care must be taken to prevent program execution from abruptly halting. Executables and libraries typically increase in size and decrease in speed.

And these are just the things we know. There is much the C++ community does not know about writing programs using exceptions, including, for the most part, how to do it correctly. There is as yet no agreement on a body of techniques that, when applied routinely, leads to software that behaves predictably and reliably when exceptions are thrown. (For insight into some of the issues involved, see the article by Tom Cargill. For information on recent progress in dealing with these issues, see the articles by Jack Reeves and Herb Sutter.)

We do know this much: programs that behave well in the presence of exceptions do so because they were designed to, not because they happen to. Exception-safe programs are not created by accident. The chances of a program behaving well in the presence of exceptions when it was not designed for exceptions are about the same as the chances of a program behaving well in the presence of multiple threads of control when it was not designed for multi-threaded execution: about zero.

That being the case, why use exceptions? Error codes have sufficed for C programmers ever since C was invented, so why mess with exceptions, especially if they're as problematic as I say? The answer is simple: exceptions cannot be ignored. If a function signals an exceptional condition by setting a status variable or returning an error code, there is no way to guarantee the function's caller will check the variable or examine the code. As a result, execution may continue long past the point where the condition was encountered. If the function signals the condition by throwing an exception, however, and that exception is not caught, program execution immediately ceases.

This is behavior that C programmers can approach only by using `setjmp` and `longjmp`. But `longjmp` exhibits a serious deficiency when used with C++: it fails to call destructors for local objects when it adjusts the stack. Most C++ programs depend on such destructors being called, so `setjmp` and `longjmp` make a poor substitute for true exceptions. If you need a way of signaling exceptional conditions that cannot be ignored, and if you must ensure that local destructors are called when searching the stack for code that can handle exceptional conditions, you need C++ exceptions. It's as simple as that.

Because we have much to learn about programming with exceptions, the Items that follow comprise an incomplete guide to writing exception-safe software. Nevertheless, they introduce important considerations for anyone using exceptions in C++. By heeding the guidance in the material below (and in the magazine articles on this CD), you'll improve the correctness, robustness, and efficiency of the software you write, and you'll sidestep many problems that commonly arise when working with exceptions.

Back to Exceptions
Continue to Item 10: Prevent resource leaks in constructors

Item 9: Use destructors to prevent resource leaks.

Say good-bye to pointers. Admit it: you never really liked them that much anyway.

Okay, you don't have to say good-bye to all pointers, but you do need to say sayonara to pointers that are used to manipulate local resources. Suppose, for example, you're writing software at the Shelter for Adorable Little Animals, an organization that finds homes for puppies and kittens. Each day the shelter creates a file containing information on the adoptions it arranged that day, and your job is to write a program to read these files and do the appropriate processing for each adoption.

A reasonable approach to this task is to define an abstract base class, `ALA` ("Adorable Little Animal"), plus concrete derived classes for puppies and kittens. A virtual function, `processAdoption`, handles the necessary species-specific processing:

    class ALA {
    public:
      virtual void processAdoption() = 0;
      ...
    };

    class Puppy: public ALA {
    public:
      virtual void processAdoption();
      ...
    };

    class Kitten: public ALA {
    public:
      virtual void processAdoption();
      ...
    };

You'll need a function that can read information from a file and produce either a `Puppy` object or a `Kitten` object, depending on the information in the file. This is a perfect job for a virtual constructor, a kind of function described in Item 25. For our purposes here, the function's declaration is all we need:

    // read animal information from s, then return a pointer
    // to a newly allocated object of the appropriate type
    ALA * readALA(istream& s);

The heart of your program is likely to be a function that looks something like this:

    void processAdoptions(istream& dataSource)
    {
      while (dataSource) {                  // while there's data
        ALA *pa = readALA(dataSource);      // get next animal
        pa->processAdoption();              // process adoption
        delete pa;                          // delete object that
      }                                     // readALA returned
    }

This function loops through the information in `dataSource`, processing each entry as it goes. The only mildly tricky thing is the need to remember to delete `pa` at the end of each iteration. This is necessary because `readALA` creates a new heap object each time it's called. Without the call to `delete`, the loop would contain a resource leak.

Now consider what would happen if `pa->processAdoption` threw an exception. `processAdoptions` fails to catch exceptions, so the exception would propagate to `processAdoptions`'s caller. In doing so, all statements in `processAdoptions` after the call to `pa->processAdoption` would be skipped, and that means `pa` would never be deleted. As a result, anytime `pa->processAdoption` throws an exception, `processAdoptions` contains a resource leak.

Plugging the leak is easy enough,

    void processAdoptions(istream& dataSource)
    {
      while (dataSource) {
        ALA *pa = readALA(dataSource);

      try {
          pa->processAdoption();
      }
      catch (...) {              // catch all exceptions

        delete pa;               // avoid resource leak when an
                                 // exception is thrown

        throw;                   // propagate exception to caller
      }

      delete pa;                 // avoid resource leak when no
     }                           // exception is thrown
    }

but then you have to litter your code with `try` and `catch` blocks. More importantly, you are forced to duplicate cleanup code that is common to both normal and exceptional paths of control. In this case, the call to `delete` must be duplicated. Like all replicated code, this is annoying to write and difficult to maintain, but it also feels wrong. Regardless of whether we leave `processAdoptions` by a normal return or by throwing an exception, we need to delete `pa`, so why should we have to say that in more than one place?

We don't have to if we can somehow move the cleanup code that must always be executed into the destructor for an object local to `processAdoptions`. That's because local objects are always destroyed when leaving a function, regardless of how that function is exited. (The only exception to this rule is when you call `longjmp`, and this shortcoming of `longjmp` is the primary reason why C++ has support for exceptions in the first place.) Our real concern, then, is moving the `delete` from `processAdoptions` into a destructor for an object local to `processAdoptions`.

The solution is to replace the pointer `pa` with an object that acts like a pointer. That way, when the pointer-like object is (automatically) destroyed, we can have its destructor call `delete`. Objects that act like pointers, but do more, are called smart pointers, and, as Item 28 explains, you can make pointer-like objects very smart indeed. In this case, we don't need a particularly brainy pointer, we just need a pointer-like object that knows enough to delete what it points to when the pointer-like object goes out of scope.

It's not difficult to write a class for such objects, but we don't need to. The standard C++ library (see Item E49) contains a class template called `auto_ptr` that does just what we want. Each `auto_ptr` class takes a pointer to a heap object in its constructor and deletes that object in its destructor. Boiled down to these essential functions, `auto_ptr` looks like this:

    template<class T>
    class auto_ptr {
    public:
      auto_ptr(T *p = 0): ptr(p) {}        // save ptr to object
      ~auto_ptr() { delete ptr; }          // delete ptr to object

    private:
      T *ptr;                              // raw ptr to object
    };

The standard version of `auto_ptr` is much fancier, and this stripped-down implementation isn't suitable for real use3 (we must add at least the copy constructor, assignment operator, and pointer-emulating functions discussed in Item 28), but the concept behind it should be clear: use `auto_ptr` objects instead of raw pointers, and you won't have to worry about heap objects not being deleted, not even when exceptions are thrown. (Because the `auto_ptr` destructor uses the single-object form of `delete`, `auto_ptr` is not suitable for use with pointers to arrays of objects. If you'd like an `auto_ptr`-like template for arrays, you'll have to write your own. In such cases, however, it's often a better design decision to use a `vector` instead of an array, anyway.)

Using an `auto_ptr` object instead of a raw pointer, `processAdoptions` looks like this:

    void processAdoptions(istream& dataSource)
    {
      while (dataSource) {
        auto_ptr<ALA> pa(readALA(dataSource));
        pa->processAdoption();
      }
    }

This version of `processAdoptions` differs from the original in only two ways. First, `pa` is declared to be an `auto_ptr<ALA>` object, not a raw `ALA*` pointer. Second, there is no `delete` statement at the end of the loop. That's it. Everything else is identical, because, except for destruction, `auto_ptr` objects act just like normal pointers. Easy, huh?

The idea behind `auto_ptr` — using an object to store a resource that needs to be automatically released and relying on that object's destructor to release it — applies to more than just pointer-based resources. Consider a function in a GUI application that needs to create a window to display some information:

    // this function may leak resources if an exception
    // is thrown
    void displayInfo(const Information& info)
    {
      WINDOW_HANDLE w(createWindow());

      display info in window corresponding to w;

      destroyWindow(w);
    }

Many window systems have C-like interfaces that use functions like `createWindow` and `destroyWindow` to acquire and release window resources. If an exception is thrown during the process of displaying `info` in `w`, the window for which `w` is a handle will be lost just as surely as any other dynamically allocated resource.

The solution is the same as it was before. Create a class whose constructor and destructor acquire and release the resource:

    // class for acquiring and releasing a window handle
    class WindowHandle {
    public:
       WindowHandle(WINDOW_HANDLE handle): w(handle) {}
      ~WindowHandle() { destroyWindow(w); }

       operator WINDOW_HANDLE() { return w; }        // see below

    private:
      WINDOW_HANDLE w;

      // The following functions are declared private to prevent
      // multiple copies of a WINDOW_HANDLE from being created.
      // See Item 28 for a discussion of a more flexible approach.
      WindowHandle(const WindowHandle&);
      WindowHandle& operator=(const WindowHandle&);
    };

This looks just like the `auto_ptr` template, except that assignment and copying are explicitly prohibited (see Item E27), and there is an implicit conversion operator that can be used to turn a `WindowHandle` into a `WINDOW_HANDLE`. This capability is essential to the practical application of a `WindowHandle` object, because it means you can use a `WindowHandle` just about anywhere you would normally use a raw `WINDOW_HANDLE`. (See Item 5, however, for why you should generally be leery of implicit type conversion operators.)

Given the `WindowHandle` class, we can rewrite `displayInfo` as follows:

    // this function avoids leaking resources if an
    // exception is thrown
    void displayInfo(const Information& info)
    {
      WindowHandle w(createWindow());

      display info in window corresponding to w;

    }

Even if an exception is thrown within `displayInfo`, the window created by `createWindow` will always be destroyed.

By adhering to the rule that resources should be encapsulated inside objects, you can usually avoid resource leaks in the presence of exceptions. But what happens if an exception is thrown while you're in the process of acquiring a resource, e.g., while you're in the constructor of a resource-acquiring class? What happens if an exception is thrown during the automatic destruction of such resources? Don't constructors and destructors call for special techniques? They do, and you can read about them in Items 10 and 11.

Back to Item 9: Use destructors to prevent resource leaks
Continue to Item 11: Prevent exceptions from leaving destructors

Item 10: Prevent resource leaks in constructors.

Imagine you're developing software for a multimedia address book. Such an address book might hold, in addition to the usual textual information of a person's name, address, and phone numbers, a picture of the person and the sound of their voice (possibly giving the proper pronunciation of their name).

To implement the book, you might come up with a design like this:

    class Image {                        // for image data
    public:
      Image(const string& imageDataFileName);
      ...
    };

    class AudioClip {                    // for audio data
    public:
      AudioClip(const string& audioDataFileName);
      ...
    };

    class PhoneNumber {         ... };   // for holding phone numbers

    class BookEntry {                    // for each entry in the
    public:                              // address book

    BookEntry(const string& name,
              const string& address = "",
              const string& imageFileName = "",
              const string& audioClipFileName = "");
    ~BookEntry();

    // phone numbers are added via this function
    void addPhoneNumber(const PhoneNumber& number);
    ...

    private:
      string theName;                 // person's name
      string theAddress;              // their address
      list<PhoneNumber> thePhones;    // their phone numbers
      Image *theImage;                // their image
      AudioClip *theAudioClip;        // an audio clip from them
    };

Each `BookEntry` must have name data, so you require that as a constructor argument (see Item 3), but the other fields — the person's address and the names of files containing image and audio data — are optional. Note the use of the `list` class to hold the person's phone numbers. This is one of several container classes that are part of the standard C++ library (see Item E49 and Item 35).

A straightforward way to write the `BookEntry` constructor and destructor is as follows:

    BookEntry::BookEntry(const string& name,
                         const string& address,
                         const string& imageFileName,
                         Const string& audioClipFileName)
    : theName(name), theAddress(address),
      theImage(0), theAudioClip(0)
    {
      if (imageFileName != "") {
        theImage = new Image(imageFileName);
      }

    if (audioClipFileName != "") {
    theAudioClip = new AudioClip(audioClipFileName);
      }
    }

    BookEntry::~BookEntry()
    {
      delete theImage;
      delete theAudioClip;
    }

The constructor initializes the pointers `theImage` and `theAudioClip` to null, then makes them point to real objects if the corresponding arguments are non-empty strings. The destructor deletes both pointers, thus ensuring that a `BookEntry` object doesn't give rise to a resource leak. Because C++ guarantees it's safe to delete null pointers, `BookEntry`'s destructor need not check to see if the pointers actually point to something before deleting them.

Everything looks fine here, and under normal conditions everything is fine, but under abnormal conditions — under exceptional conditions — things are not fine at all.

Consider what will happen if an exception is thrown during execution of this part of the `BookEntry` constructor:

    if (audioClipFileName != "") {
      theAudioClip = new AudioClip(audioClipFileName);
    }

An exception might arise because `operator` `new` (see Item 8) is unable to allocate enough memory for an `AudioClip` object. One might also arise because the `AudioClip` constructor itself throws an exception. Regardless of the cause of the exception, if one is thrown within the `BookEntry` constructor, it will be propagated to the site where the `BookEntry` object is being created.

Now, if an exception is thrown during creation of the object `theAudioClip` is supposed to point to (thus transferring control out of the `BookEntry` constructor), who deletes the object that `theImage` already points to? The obvious answer is that `BookEntry`'s destructor does, but the obvious answer is wrong. `BookEntry`'s destructor will never be called. Never.

C++ destroys only fully constructed objects, and an object isn't fully constructed until its constructor has run to completion. So if a `BookEntry` object `b` is created as a local object,

    void testBookEntryClass()
    {
      BookEntry b("Addison-Wesley Publishing Company",
                  "One Jacob Way, Reading, MA 01867");

    ...

    }

and an exception is thrown during construction of `b`, `b`'s destructor will not be called. Furthermore, if you try to take matters into your own hands by allocating `b` on the heap and then calling `delete` if an exception is thrown,

    void testBookEntryClass()
    {
      BookEntry *pb = 0;

      try {
        pb = new BookEntry("Addison-Wesley Publishing Company",
                           "One Jacob Way, Reading, MA 01867");
        ...
      }
      catch (...) {                // catch all exceptions

         delete pb;                // delete pb when an
                                   // exception is thrown

         throw;                    // propagate exception to
      }                            // caller

      delete pb;                   // delete pb normally
    }

you'll find that the `Image` object allocated inside `BookEntry`'s constructor is still lost, because no assignment is made to `pb` unless the `new` operation succeeds. If `BookEntry`'s constructor throws an exception, `pb` will be the null pointer, so deleting it in the `catch` block does nothing except make you feel better about yourself. Using the smart pointer class `auto_ptr<BookEntry>` (see Item 9) instead of a raw `BookEntry*` won't do you any good either, because the assignment to `pb` still won't be made unless the `new` operation succeeds.

There is a reason why C++ refuses to call destructors for objects that haven't been fully constructed, and it's not simply to make your life more difficult. It's because it would, in many cases, be a nonsensical thing — possibly a harmful thing — to do. If a destructor were invoked on an object that wasn't fully constructed, how would the destructor know what to do? The only way it could know would be if bits had been added to each object indicating how much of the constructor had been executed. Then the destructor could check the bits and (maybe) figure out what actions to take. Such bookkeeping would slow down constructors, and it would make each object larger, too. C++ avoids this overhead, but the price you pay is that partially constructed objects aren't automatically destroyed. (For an example of a similar trade-off involving efficiency and program behavior, turn to Item E13.)

Because C++ won't clean up after objects that throw exceptions during construction, you must design your constructors so that they clean up after themselves. Often, this involves simply catching all possible exceptions, executing some cleanup code, then rethrowing the exception so it continues to propagate. This strategy can be incorporated into the `BookEntry` constructor like this:

    BookEntry::BookEntry(const string& name,
              	     const string& address,
              	     const string& imageFileName,
    	      	     const string& audioClipFileName)
    : theName(name), theAddress(address),
      theImage(0), theAudioClip(0)
    {
      try {                            // this try block is new
        if (imageFileName != "") {
          theImage = new Image(imageFileName);
        }

      if (audioClipFileName != "") {
          theAudioClip = new AudioClip(audioClipFileName);
        }
      }
      catch (...) {                      // catch any exception

        delete theImage;                 // perform necessary
        delete theAudioClip;             // cleanup actions

        throw;                           // propagate the exception
      }
    }

There is no need to worry about `BookEntry`'s non-pointer data members. Data members are automatically initialized before a class's constructor is called, so if a `BookEntry` constructor body begins executing, the object's `theName`, `theAddress`, and `thePhones` data members have already been fully constructed. As fully constructed objects, these data members will be automatically destroyed when the `BookEntry` object containing them is, and there is no need for you to intervene. Of course, if these objects' constructors call functions that might throw exceptions, those constructors have to worry about catching the exceptions and performing any necessary cleanup before allowing them to propagate.

You may have noticed that the statements in `BookEntry`'s `catch` block are almost the same as those in `BookEntry`'s destructor. Code duplication here is no more tolerable than it is anywhere else, so the best way to structure things is to move the common code into a private helper function and have both the constructor and the destructor call it:

    class BookEntry {
    public:
      ...                      // as before

    private:
      ...
      void cleanup();          // common cleanup statements
    };

    void BookEntry::cleanup()
    {
      delete theImage;
      delete theAudioClip;
    }

    BookEntry::BookEntry(const string& name,
                         const string& address,
             	     const string& imageFileName,
              	     const string& audioClipFileName)
    : theName(name), theAddress(address),
      theImage(0), theAudioClip(0)
    {
      try {
        ...                   // as before
      }
      catch (...)   {
        cleanup();            // release resources
        throw;                // propagate exception
      }
    }

    BookEntry::~BookEntry()
    {
      cleanup();
    }

This is nice, but it doesn't put the topic to rest. Let us suppose we design our `BookEntry` class slightly differently so that `theImage` and `theAudioClip` are constant pointers:

    class BookEntry {
    public:
      ...                                  // as above

    private:
      ...
      Image * const theImage;              // pointers are now
      AudioClip * const theAudioClip;      // const
    };

Such pointers must be initialized via the member initialization lists of `BookEntry`'s constructors, because there is no other way to give `const` pointers a value (see Item E12). A common temptation is to initialize `theImage` and `theAudioClip` like this,

    // an implementation that may leak resources if an
    // exception is thrown
    BookEntry::BookEntry(const string& name,
                         const string& address,
                         const string& imageFileName,
                         const string& audioClipFileName)
    : theName(name), theAddress(address),
      theImage(imageFileName != ""
            ? new Image(imageFileName)
            : 0),
      theAudioClip(audioClipFileName != ""
              ? new AudioClip(audioClipFileName)
              : 0)
    {}

but this leads to the problem we originally wanted to eliminate: if an exception is thrown during initialization of `theAudioClip`, the object pointed to by `theImage` is never destroyed. Furthermore, we can't solve the problem by adding `try` and `catch` blocks to the constructor, because `try` and `catch` are statements, and member initialization lists allow only expressions. (That's why we had to use the `?:` syntax instead of the `if`-`then`-`else` syntax in the initialization of `theImage` and `theAudioClip`.)

Nevertheless, the only way to perform cleanup chores before exceptions propagate out of a constructor is to catch those exceptions, so if we can't put `try` and `catch` in a member initialization list, we'll have to put them somewhere else. One possibility is inside private member functions that return pointers with which `theImage` and `theAudioClip` should be initialized:

    class BookEntry {
    public:
      ...                     // as above

    private:
      ...                     // data members as above

    Image * initImage(const string& imageFileName);
      AudioClip * initAudioClip(const string&
                                audioClipFileName);
    };

    BookEntry::BookEntry(const string& name,
                         const string& address,
                         const string& imageFileName,
                         const string& audioClipFileName)
    : theName(name), theAddress(address),
      theImage(initImage(imageFileName)),
      theAudioClip(initAudioClip(audioClipFileName))
    {}

    // theImage is initialized first, so there is no need to
    // worry about a resource leak if this initialization
    // fails. This function therefore handles no exceptions
    Image * BookEntry::initImage(const string& imageFileName)
    {
      if (imageFileName != "") return new Image(imageFileName);
      else return 0;
    }

    // theAudioClip is initialized second, so it must make
    // sure theImage's resources are released if an exception
    // is thrown during initialization of theAudioClip. That's
    // why this function uses try...catch.
    AudioClip * BookEntry::initAudioClip(const string&
                                         audioClipFileName)
    {
      try {
        if (audioClipFileName != "") {
          return new AudioClip(audioClipFileName);
        }
        else return 0;
      }
      catch (...)   {
        delete theImage;
        throw;
      }
    }

This is perfectly kosher, and it even solves the problem we've been laboring to overcome. The drawback is that code that conceptually belongs in a constructor is now dispersed across several functions, and that's a maintenance headache.

A better solution is to adopt the advice of Item 9 and treat the objects pointed to by `theImage` and `theAudioClip` as resources to be managed by local objects. This solution takes advantage of the facts that both `theImage` and `theAudioClip` are pointers to dynamically allocated objects and that those objects should be deleted when the pointers themselves go away. This is precisely the set of conditions for which the `auto_ptr` classes (see Item 9) were designed. We can therefore change the raw pointer types of `theImage` and `theAudioClip` to their `auto_ptr` equivalents:

    class BookEntry {
    public:
      ...                                      // as above

    private:
      ...
      const auto_ptr<Image> theImage;          // these are now
      const auto_ptr<AudioClip> theAudioClip;  // auto_ptr objects
    };

Doing this makes `BookEntry`'s constructor leak-safe in the presence of exceptions, and it lets us initialize `theImage` and `theAudioClip` using the member initialization list:

    BookEntry::BookEntry(const string& name,
                         const string& address,
                         const string& imageFileName,
                         const string& audioClipFileName)
    : theName(name), theAddress(address),
      theImage(imageFileName != ""
            ? new Image(imageFileName)
            : 0),
      theAudioClip(audioClipFileName != ""
              ? new AudioClip(audioClipFileName)
              : 0)
    {}

In this design, if an exception is thrown during initialization of `theAudioClip`, `theImage` is already a fully constructed object, so it will automatically be destroyed, just like `theName`, `theAddress`, and `thePhones`. Furthermore, because `theImage` and `theAudioClip` are now objects, they'll be destroyed automatically when the `BookEntry` object containing them is. Hence there's no need to manually delete what they point to. That simplifies `BookEntry`'s destructor considerably:

    BookEntry::~BookEntry()
    {}                                      // nothing to do!

This means you could eliminate `BookEntry`'s destructor entirely.

It all adds up to this: if you replace pointer class members with their corresponding `auto_ptr` objects, you fortify your constructors against resource leaks in the presence of exceptions, you eliminate the need to manually deallocate resources in destructors, and you allow `const` member pointers to be handled in the same graceful fashion as non-`const` pointers.

Dealing with the possibility of exceptions during construction can be tricky, but `auto_ptr` (and `auto_ptr`-like classes) can eliminate most of the drudgery. Their use leaves behind code that's not only easy to understand, it's robust in the face of exceptions, too.

Back to Item 10: Prevent resource leaks in constructors
Continue to Item 12: Understand how throwing an exception differs from passing a parameter or calling a virtual function

Item 11: Prevent exceptions from leaving destructors.

There are two situations in which a destructor is called. The first is when an object is destroyed under "normal" conditions, e.g., when it goes out of scope or is explicitly `delete`d. The second is when an object is destroyed by the exception-handling mechanism during the stack-unwinding part of exception propagation.

That being the case, an exception may or may not be active when a destructor is invoked. Regrettably, there is no way to distinguish between these conditions from inside a destructor.4 As a result, you must write your destructors under the conservative assumption that an exception is active, because if control leaves a destructor due to an exception while another exception is active, C++ calls the `terminate` function. That function does just what its name suggests: it terminates execution of your program. Furthermore, it terminates it immediately; not even local objects are destroyed.

As an example, consider a `Session` class for monitoring on-line computer sessions, i.e., things that happen from the time you log in through the time you log out. Each `Session` object notes the date and time of its creation and destruction:

    class Session {
    public:
      Session();
      ~Session();
      ...

    private:
      static void logCreation(Session *objAddr);
      static void logDestruction(Session *objAddr);
    };

The functions `logCreation` and `logDestruction` are used to record object creations and destructions, respectively. We might therefore expect that we could code `Session`'s destructor like this:

    Session::~Session()
    {
      logDestruction(this);
    }

This looks fine, but consider what would happen if `logDestruction` throws an exception. The exception would not be caught in `Session`'s destructor, so it would be propagated to the caller of that destructor. But if the destructor was itself being called because some other exception had been thrown, the `terminate` function would automatically be invoked, and that would stop your program dead in its tracks.

In many cases, this is not what you'll want to have happen. It may be unfortunate that the `Session` object's destruction can't be logged, it might even be a major inconvenience, but is it really so horrific a prospect that the program can't continue running? If not, you'll have to prevent the exception thrown by `logDestruction` from propagating out of `Session`'s destructor. The only way to do that is by using `try` and `catch` blocks. A naive attempt might look like this,

    Session::~Session()
    {
      try {
        logDestruction(this);
      }
      catch (...) {
        cerr  << "Unable to log destruction of Session object "
              << "at address "
              << this
              << ".\n";
      }
    }

but this is probably no safer than our original code. If one of the calls to `operator<<` in the `catch` block results in an exception being thrown, we're back where we started, with an exception leaving the `Session` destructor.

We could always put a `try` block inside the `catch` block, but that seems a bit extreme. Instead, we'll just forget about logging `Session` destructions if `logDestruction` throws an exception:

    Session::~Session()
    {
      try {
        logDestruction(this);
      }
      catch (...) {  }
    }

The `catch` block appears to do nothing, but appearances can be deceiving. That block prevents exceptions thrown from `logDestruction` from propagating beyond `Session`'s destructor. That's all it needs to do. We can now rest easy knowing that if a `Session` object is destroyed as part of stack unwinding, `terminate` will not be called.

There is a second reason why it's bad practice to allow exceptions to propagate out of destructors. If an exception is thrown from a destructor and is not caught there, that destructor won't run to completion. (It will stop at the point where the exception is thrown.) If the destructor doesn't run to completion, it won't do everything it's supposed to do. For example, consider a modified version of the `Session` class where the creation of a session starts a database transaction and the termination of a session ends that transaction:

    Session::Session()          // to keep things simple,
    {                           // this ctor handles no
                                // exceptions
      logCreation(this);
      startTransaction();       // start DB transaction
    }

    Session::~Session()
    {
      logDestruction(this);
      endTransaction();         // end DB transaction
    }

Here, if `logDestruction` throws an exception, the transaction started in the `Session` constructor will never be ended. In this case, we might be able to reorder the function calls in `Session`'s destructor to eliminate the problem, but if `endTransaction` might throw an exception, we've no choice but to revert to `try` and `catch` blocks.

We thus find ourselves with two good reasons for keeping exceptions from propagating out of destructors. First, it prevents `terminate` from being called during the stack-unwinding part of exception propagation. Second, it helps ensure that destructors always accomplish everything they are supposed to accomplish. Each argument is convincing in its own right, but together, the case is ironclad. (If you're still not convinced, turn to Herb Sutter's article; in particular, to the section entitled, "Destructors That Throw and Why They're Evil.)

Back to Item 11: Prevent exceptions from leaving destructors
Continue to Item 13: Catch exceptions by reference

Item 12: Understand how throwing an exception differs from passing a parameter or calling a virtual function.

The syntax for declaring function parameters is almost the same as that for `catch` clauses:

    class Widget { ... };                 // some class; it makes no
                                          // difference what it is

    void f1(Widget w);                    // all these functions
    void f2(Widget& w);                   // take parameters of
    void f3(const Widget& w);             // type Widget, Widget&, or
    void f4(Widget *pw);                  // Widget*
    void f5(const Widget *pw);

    catch (Widget w) ...                  // all these catch clauses
    catch (Widget& w)   ...               // catch exceptions of
    catch (const Widget& w) ...           // type Widget, Widget&, or
    catch (Widget *pw) ...                // Widget*
    catch (const Widget *pw) ...

You might therefore assume that passing an exception from a `throw` site to a `catch` clause is basically the same as passing an argument from a function call site to the function's parameter. There are some similarities, to be sure, but there are significant differences, too.

Let us begin with a similarity. You can pass both function parameters and exceptions by value, by reference, or by pointer. What happens when you pass parameters and exceptions, however, is quite different. This difference grows out of the fact that when you call a function, control eventually returns to the call site (unless the function fails to return), but when you throw an exception, control does not return to the `throw` site.

Consider a function that both passes a `Widget` as a parameter and throws a `Widget` as an exception:

    // function to read the value of a Widget from a stream
    istream operator>>(istream& s, Widget& w);

    void passAndThrowWidget()
    {
      Widget localWidget;

      cin >> localWidget;          // pass localWidget to operator>>

      throw localWidget;           // throw localWidget as an exception
    }

When `localWidget` is passed to `operator>>`, no copying is performed. Instead, the reference `w` inside `operator>>` is bound to `localWidget`, and anything done to `w` is really done to `localWidget`. It's a different story when `localWidget` is thrown as an exception. Regardless of whether the exception is caught by value or by reference (it can't be caught by pointer — that would be a type mismatch), a copy of `localWidget` will be made, and it is the copy that is passed to the `catch` clause. This must be the case, because `localWidget` will go out of scope once control leaves `passAndThrowWidget`, and when `localWidget` goes out of scope, its destructor will be called. If `localWidget` itself were passed to a `catch` clause, the clause would receive a destructed `Widget`, an ex-`Widget`, a former `Widget`, the carcass of what once was but is no longer a `Widget`. That would not be useful, and that's why C++ specifies that an object thrown as an exception is always copied.

This copying occurs even if the object being thrown is not in danger of being destroyed. For example, if `passAndThrowWidget` declares `localWidget` to be static,

    void passAndThrowWidget()
    {
      static Widget localWidget;        // this is now static; it
                                        // will exist until the
                                        // end of the program

      cin >> localWidget;               // this works as before

      throw localWidget;                // a copy of localWidget is
    }                                   // still made and thrown

a copy of `localWidget` would still be made when the exception was thrown. This means that even if the exception is caught by reference, it is not possible for the `catch` block to modify `localWidget`; it can only modify a copy of `localWidget`. This mandatory copying of exception objects helps explain another difference between parameter passing and throwing an exception: the latter is typically much slower than the former (see Item 15).

When an object is copied for use as an exception, the copying is performed by the object's copy constructor. This copy constructor is the one in the class corresponding to the object's static type, not its dynamic type. For example, consider this slightly modified version of `passAndThrowWidget`:

    class Widget { ... };
    class SpecialWidget: public Widget { ... };

    void passAndThrowWidget()
    {
      SpecialWidget localSpecialWidget;

      ...

      Widget& rw = localSpecialWidget;      // rw refers to a
                                            // SpecialWidget

      throw rw;                             // this throws an
                                            // exception of type
    }                                       // Widget!

Here a `Widget` exception is thrown, even though `rw` refers to a `SpecialWidget`. That's because `rw`'s static type is `Widget`, not `SpecialWidget`. That `rw` actually refers to a `SpecialWidget` is of no concern to your compilers; all they care about is `rw`'s static type. This behavior may not be what you want, but it's consistent with all other cases in which C++ copies objects. Copying is always based on an object's static type (but see Item 25 for a technique that lets you make copies on the basis of an object's dynamic type).

The fact that exceptions are copies of other objects has an impact on how you propagate exceptions from a `catch` block. Consider these two `catch` blocks, which at first glance appear to do the same thing:

    catch (Widget& w)                 // catch Widget exceptions
    {
      ...                             // handle the exception

      throw;                          // rethrow the exception so it
    }                                 // continues to propagate

    catch (Widget& w)                 // catch Widget exceptions
    {
      ...                             // handle the exception

      throw w;                        // propagate a copy of the
    }                                 // caught exception

The only difference between these blocks is that the first one rethrows the current exception, while the second one throws a new copy of the current exception. Setting aside the performance cost of the additional copy operation, is there a difference between these approaches?

There is. The first block rethrows the current exception, regardless of its type. In particular, if the exception originally thrown was of type `SpecialWidget`, the first block would propagate a `SpecialWidget` exception, even though `w`'s static type is `Widget`. This is because no copy is made when the exception is rethrown. The second `catch` block throws a new exception, which will always be of type `Widget`, because that's `w`'s static type. In general, you'll want to use the

    throw;

syntax to rethrow the current exception, because there's no chance that that will change the type of the exception being propagated. Furthermore, it's more efficient, because there's no need to generate a new exception object.

(Incidentally, the copy made for an exception is a temporary object. As Item 19 explains, this gives compilers the right to optimize it out of existence. I wouldn't expect your compilers to work that hard, however. Exceptions are supposed to be rare, so it makes little sense for compiler vendors to pour a lot of energy into their optimization.)

Let us examine the three kinds of `catch` clauses that could catch the `Widget` exception thrown by `passAndThrowWidget`. They are:

    catch (Widget w) ...                // catch exception by value

    catch (Widget& w) ...               // catch exception by
                                        // reference

    catch (const Widget& w) ...         // catch exception by
                                        // reference-to-const

Right away we notice another difference between parameter passing and exception propagation. A thrown object (which, as explained above, is always a temporary) may be caught by simple reference; it need not be caught by reference-to-`const`. Passing a temporary object to a non-`const` reference parameter is not allowed for function calls (see Item 19), but it is for exceptions.

Let us overlook this difference, however, and return to our examination of copying exception objects. We know that when we pass a function argument by value, we make a copy of the passed object (see Item E22), and we store that copy in a function parameter. The same thing happens when we pass an exception by value. Thus, when we declare a `catch` clause like this,

    catch (Widget w) ...                // catch by value

we expect to pay for the creation of two copies of the thrown object, one to create the temporary that all exceptions generate, the second to copy that temporary into `w`. Similarly, when we catch an exception by reference,

    catch (Widget& w) ...               // catch by reference

    catch (const Widget& w) ...         // also catch by reference

we still expect to pay for the creation of a copy of the exception: the copy that is the temporary. In contrast, when we pass function parameters by reference, no copying takes place. When throwing an exception, then, we expect to construct (and later destruct) one more copy of the thrown object than if we passed the same object to a function.

We have not yet discussed throwing exceptions by pointer, but throw by pointer is equivalent to pass by pointer. Either way, a copy of the pointer is passed. About all you need to remember is not to throw a pointer to a local object, because that local object will be destroyed when the exception leaves the local object's scope. The `catch` clause would then be initialized with a pointer to an object that had already been destroyed. This is the behavior the mandatory copying rule is designed to avoid.

The way in which objects are moved from call or `throw` sites to parameters or `catch` clauses is one way in which argument passing differs from exception propagation. A second difference lies in what constitutes a type match between caller or thrower and callee or catcher. Consider the `sqrt` function from the standard math library:

    double sqrt(double);                 // from <cmath> or <math.h>

We can determine the square root of an integer like this:

    int i;

    double sqrtOfi = sqrt(i);

There is nothing surprising here. The language allows implicit conversion from `int` to `double`, so in the call to `sqrt`, `i` is silently converted to a `double`, and the result of `sqrt` corresponds to that `double`. (See Item 5 for a fuller discussion of implicit type conversions.) In general, such conversions are not applied when matching exceptions to `catch` clauses. In this code,

    void f(int value)
    {
      try {
        if (someFunction()) {      // if someFunction() returns
          throw value;             // true, throw an int
        ...
        }
      }
      catch (double d) {           // handle exceptions of
        ...                        // type double here
      }

      ...

    }

the `int` exception thrown inside the `try` block will never be caught by the `catch` clause that takes a `double`. That clause catches only exceptions that are exactly of type `double`; no type conversions are applied. As a result, if the `int` exception is to be caught, it will have to be by some other (dynamically enclosing) `catch` clause taking an `int` or an `int&` (possibly modified by `const` or `volatile`).

Two kinds of conversions are applied when matching exceptions to `catch` clauses. The first is inheritance-based conversions. A `catch` clause for base class exceptions is allowed to handle exceptions of derived class types, too. For example, consider the diagnostics portion of the hierarchy of exceptions defined by the standard C++ library (see Item E49):

A `catch` clause for `runtime_error`s can catch exceptions of type `range_error` and `overflow_error`, too, and a `catch` clause accepting an object of the root class `exception` can catch any kind of exception derived from this hierarchy.

This inheritance-based exception-conversion rule applies to values, references, and pointers in the usual fashion:

    catch (runtime_error) ...               // can catch errors of type
    catch (runtime_error&) ...              // runtime_error,
    catch (const runtime_error&) ...        // range_error, or
                                            // overflow_error

    catch (runtime_error*) ...              // can catch errors of type
    catch (const runtime_error*) ...        // runtime_error*,
                                            // range_error*, or
                                            // overflow_error*

The second type of allowed conversion is from a typed to an untyped pointer, so a `catch` clause taking a `const` `void*` pointer will catch an exception of any pointer type:

    catch (const void*) ...                 // catches any exception
                                            // that's a pointer

The final difference between passing a parameter and propagating an exception is that `catch` clauses are always tried in the order of their appearance. Hence, it is possible for an exception of a derived class type to be handled by a `catch` clause for one of its base class types — even when a `catch` clause for the derived class is associated with the same `try` block! For example,

    try {
      ...
    }
    catch (logic_error& ex) {              // this block will catch
      ...                                  // all logic_error
    }                                      // exceptions, even those
                                           // of derived types

    catch (invalid_argument& ex) {         // this block can never be
      ...                                  // executed, because all
    }                                      // invalid_argument
                                           // exceptions will be caught
                                           // by the clause above

Contrast this behavior with what happens when you call a virtual function. When you call a virtual function, the function invoked is the one in the class closest to the dynamic type of the object invoking the function. You might say that virtual functions employ a "best fit" algorithm, while exception handling follows a "first fit" strategy. Compilers may warn you if a `catch` clause for a derived class comes after one for a base class (some issue an error, because such code used to be illegal in C++), but your best course of action is preemptive: never put a `catch` clause for a base class before a `catch` clause for a derived class. The code above, for example, should be reordered like this:

    try {
      ...
    }
    catch (invalid_argument& ex) {          // handle invalid_argument
      ...                                   // exceptions here
    }
    catch (logic_error& ex) {               // handle all other
      ...                                   // logic_errors here
    }

There are thus three primary ways in which passing an object to a function or using that object to invoke a virtual function differs from throwing the object as an exception. First, exception objects are always copied; when caught by value, they are copied twice. Objects passed to function parameters need not be copied at all. Second, objects thrown as exceptions are subject to fewer forms of type conversion than are objects passed to functions. Finally, `catch` clauses are examined in the order in which they appear in the source code, and the first one that can succeed is selected for execution. When an object is used to invoke a virtual function, the function selected is the one that provides the best match for the type of the object, even if it's not the first one listed in the source code.

Back to Item 12: Understand how throwing an exception differs from passing a parameter or calling a virtual function
Continue to Item 14: Use exception specifications judiciously

Item 13: Catch exceptions by reference.

When you write a `catch` clause, you must specify how exception objects are to be passed to that clause. You have three choices, just as when specifying how parameters should be passed to functions: by pointer, by value, or by reference.

Let us consider first catch by pointer. In theory, this should be the least inefficient way to implement the invariably slow process of moving an exception from `throw` site to `catch` clause (see Item 15). That's because throw by pointer is the only way of moving exception information without copying an object (see Item 12). For example:

    class exception { ... };          // from the standard C++
                                      // library exception
                                      // hierarchy (see Item 12)

    void someFunction()
    {
      static exception ex;            // exception object

    ...

      throw &ex;                      // throw a pointer to ex

      ...

    }

    void doSomething()
    {
      try {
        someFunction();               // may throw an exception*
      }
      catch (exception *ex) {         // catches the exception*;
        ...                           // no object is copied
      }
    }

This looks neat and tidy, but it's not quite as well-kept as it appears. For this to work, programmers must define exception objects in a way that guarantees the objects exist after control leaves the functions throwing pointers to them. Global and static objects work fine, but it's easy for programmers to forget the constraint. If they do, they typically end up writing code like this:

    void someFunction()
    {
      exception ex;                   // local exception object;
                                      // will be destroyed when
                                      // this function's scope is
      ...                             // exited

      throw &ex;                      // throw a pointer to an
      ...                             // object that's about to
    }                                 // be destroyed

This is worse than useless, because the `catch` clause handling this exception receives a pointer to an object that no longer exists.

An alternative is to throw a pointer to a new heap object:

    void someFunction()
    {
      ...
      throw new exception;            // throw a pointer to a new heap-
      ...                             // based object (and hope that
    }                                 // operator new — see Item 8 —
                                      // doesn't itself throw an
                                      // exception!)

This avoids the I-just-caught-a-pointer-to-a-destroyed-object problem, but now authors of `catch` clauses confront a nasty question: should they delete the pointer they receive? If the exception object was allocated on the heap, they must, otherwise they suffer a resource leak. If the exception object wasn't allocated on the heap, they mustn't, otherwise they suffer undefined program behavior. What to do?

It's impossible to know. Some clients might pass the address of a global or static object, others might pass the address of an exception on the heap. Catch by pointer thus gives rise to the Hamlet conundrum: to delete or not to delete? It's a question with no good answer. You're best off ducking it.

Furthermore, catch-by-pointer runs contrary to the convention established by the language itself. The four standard exceptions — `bad_alloc` (thrown when `operator` `new` (see Item 8) can't satisfy a memory request), `bad_cast` (thrown when a `dynamic_cast` to a reference fails; see Item 2), `bad_typeid` (thrown when `dynamic_cast` is applied to a null pointer), and `bad_exception` (available for unexpected exceptions; see Item 14) — are all objects, not pointers to objects, so you have to catch them by value or by reference, anyway.

Catch-by-value eliminates questions about exception deletion and works with the standard exception types. However, it requires that exception objects be copied twice each time they're thrown (see Item 12). It also gives rise to the specter of the slicing problem, whereby derived class exception objects caught as base class exceptions have their derivedness "sliced off." Such "sliced" objects are base class objects: they lack derived class data members, and when virtual functions are called on them, they resolve to virtual functions of the base class. (Exactly the same thing happens when an object is passed to a function by value — see Item E22.) For example, consider an application employing an exception class hierarchy that extends the standard one:

    class exception {                   // as above, this is a
    public:                             // standard exception class

    virtual const char * what() throw();
                                        // returns a brief descrip.
      ...                               // of the exception (see
                                        // Item 14 for info about
    };                                  // the "throw()" at the
                                        // end of the declaration)

    class runtime_error:                // also from the standard
      public exception { ... };         // C++ exception hierarchy

    class Validation_error:             // this is a class added by
      public runtime_error {            // a client
    public:
      virtual const char * what() throw();
                                        // this is a redefinition
      ...                               // of the function declared
    };                                  // in class exception above

    void someFunction()                 // may throw a validation
    {                                   // exception
      ...

      if (a validation test fails) {
        throw Validation_error();
      }

    ...

    }

    void doSomething()
    {
      try {
        someFunction();                 // may throw a validation
      }                                 // exception

      catch (exception ex) {            // catches all exceptions
                                        // in or derived from
                                        // the standard hierarchy

        cerr << ex.what();              // calls exception::what(),
        ...                             // never
      }                                 // Validation_error::what()
    }

The version of `what` that is called is that of the base class, even though the thrown exception is of type `Validation_error` and `Validation_error` redefines that virtual function. This kind of slicing behavior is almost never what you want.

That leaves only catch-by-reference. Catch-by-reference suffers from none of the problems we have discussed. Unlike catch-by-pointer, the question of object deletion fails to arise, and there is no difficulty in catching the standard exception types. Unlike catch-by-value, there is no slicing problem, and exception objects are copied only once.

If we rewrite the last example using catch-by-reference, it looks like this:

    void someFunction()                  // nothing changes in this
    {                                    // function
      ...

      if (a validation test fails) {
        throw Validation_error();
      }

      ...

    }

    void doSomething()
    {
      try {
        someFunction();                  // no change here
      }
      catch (exception& ex) {            // here we catch by reference
                                         // instead of by value

        cerr << ex.what();               // now calls
                                         // Validation_error::what(),
        ...                              // not exception::what()
      }
    }

There is no change at the `throw` site, and the only change in the `catch` clause is the addition of an ampersand. This tiny modification makes a big difference, however, because virtual functions in the `catch` block now work as we expect: functions in `Validation_error` are invoked if they redefine those in `exception`.

What a happy confluence of events! If you catch by reference, you sidestep questions about object deletion that leave you damned if you do and damned if you don't; you avoid slicing exception objects; you retain the ability to catch standard exceptions; and you limit the number of times exception objects need to be copied. So what are you waiting for? Catch exceptions by reference!

Back to Item 13: Catch exceptions by reference
Continue to Item 15: Understand the costs of exception handling

Item 14: Use exception specifications judiciously.

There's no denying it: exception specifications have appeal. They make code easier to understand, because they explicitly state what exceptions a function may throw. But they're more than just fancy comments. Compilers are sometimes able to detect inconsistent exception specifications during compilation. Furthermore, if a function throws an exception not listed in its exception specification, that fault is detected at runtime, and the special function `unexpected` is automatically invoked. Both as a documentation aid and as an enforcement mechanism for constraints on exception usage, then, exception specifications seem attractive.

As is often the case, however, beauty is only skin deep. The default behavior for `unexpected` is to call `terminate`, and the default behavior for `terminate` is to call `abort`, so the default behavior for a program with a violated exception specification is to halt. Local variables in active stack frames are not destroyed, because `abort` shuts down program execution without performing such cleanup. A violated exception specification is therefore a cataclysmic thing, something that should almost never happen.

Unfortunately, it's easy to write functions that make this terrible thing occur. Compilers only partially check exception usage for consistency with exception specifications. What they do not check for — what the °language standard prohibits them from rejecting (though they may issue a warning) — is a call to a function that might violate the exception specification of the function making the call.

Consider a declaration for a function `f1` that has no exception specification. Such a function may throw any kind of exception:

    extern void f1();                  // might throw anything

Now consider a function `f2` that claims, through its exception specification, it will throw only exceptions of type `int`:

    void f2() throw(int);

It is perfectly legal C++ for `f2` to call `f1`, even though `f1` might throw an exception that would violate `f2`'s exception specification:

    void f2() throw(int)
    {
      ...
      f1();                  // legal even though f1 might throw
                             // something besides an int
      ...
    }

This kind of flexibility is essential if new code with exception specifications is to be integrated with older code lacking such specifications.

Because your compilers are content to let you call functions whose exception specifications are inconsistent with those of the routine containing the calls, and because such calls might result in your program's execution being terminated, it's important to write your software in such a way that these kinds of inconsistencies are minimized. A good way to start is to avoid putting exception specifications on templates that take type arguments. Consider this template, which certainly looks as if it couldn't throw any exceptions:

    // a poorly designed template wrt exception specifications
    template<class T>
    bool operator==(const T& lhs, const T& rhs) throw()
    {
      return &lhs == &rhs;
    }

This template defines an `operator==` function for all types. For any pair of objects of the same type, it returns `true` if the objects have the same address, otherwise it returns `false`.

This template contains an exception specification stating that the functions generated from the template will throw no exceptions. But that's not necessarily true, because it's possible that `operator&` (the address-of operator — see Item E45) has been overloaded for some types. If it has, `operator&` may throw an exception when called from inside `operator==`. If it does, our exception specification is violated, and off to `unexpected` we go.

This is a specific example of a more general problem, namely, that there is no way to know anything about the exceptions thrown by a template's type parameters. We can almost never provide a meaningful exception specification for a template, because templates almost invariably use their type parameter in some way. The conclusion? Templates and exception specifications don't mix.

A second technique you can use to avoid calls to `unexpected` is to omit exception specifications on functions making calls to functions that themselves lack exception specifications. This is simple common sense, but there is one case that is easy to forget. That's when allowing users to register callback functions:

    // Function pointer type for a window system callback
    // when a window system event occurs
    typedef void (*CallBackPtr)(int eventXLocation,
                                int eventYLocation,
                                void *dataToPassBack);

    // Window system class for holding onto callback
    // functions registered by window system clients
    class CallBack {
    public:
      CallBack(CallBackPtr fPtr, void *dataToPassBack)
      : func(fPtr), data(dataToPassBack) {}

      void makeCallBack(int eventXLocation,
                        int eventYLocation) const throw();

    private:
      CallBackPtr func;               // function to call when
                                      // callback is made

       void *data;                       // data to pass to callback
    };                                // function

    // To implement the callback, we call the registered func-
    // tion with event's coordinates and the registered data
    void CallBack::makeCallBack(int eventXLocation,
                                int eventYLocation) const throw()
    {
      func(eventXLocation, eventYLocation, data);
    }

Here the call to `func` in `makeCallBack` runs the risk of a violated exception specification, because there is no way of knowing what exceptions `func` might throw.

This problem can be eliminated by tightening the exception specification in the `CallBackPtr` typedef:5

    typedef void (*CallBackPtr)(int eventXLocation,
                                int eventYLocation,
                                void *dataToPassBack) throw();

Given this typedef, it is now an error to register a `callback` function that fails to guarantee it throws nothing:

    // a callback function without an exception specification
    void callBackFcn1(int eventXLocation, int eventYLocation,
                      void *dataToPassBack);

    void *callBackData;

    ...

    CallBack c1(callBackFcn1, callBackData);
                                   // error! callBackFcn1
                                   // might throw an exception

    // a callback function with an exception specification
    void callBackFcn2(int eventXLocation,
                      int eventYLocation,
                      void *dataToPassBack) throw();

    CallBack c2(callBackFcn2, callBackData);
                                   // okay, callBackFcn2 has a
                                   // conforming ex. spec.

This checking of exception specifications when passing function pointers is a relatively recent addition to the language, so don't be surprised if your compilers don't yet support it. If they don't, it's up to you to ensure you don't make this kind of mistake.

A third technique you can use to avoid calls to `unexpected` is to handle exceptions "the system" may throw. Of these exceptions, the most common is `bad_alloc`, which is thrown by `operator` `new` and `operator` `new[]` when a memory allocation fails (see Item 8). If you use the `new` operator (again, see Item 8) in any function, you must be prepared for the possibility that the function will encounter a `bad_alloc` exception.

Now, an ounce of prevention may be better than a pound of cure, but sometimes prevention is hard and cure is easy. That is, sometimes it's easier to cope with unexpected exceptions directly than to prevent them from arising in the first place. If, for example, you're writing software that uses exception specifications rigorously, but you're forced to call functions in libraries that don't use exception specifications, it's impractical to prevent unexpected exceptions from arising, because that would require changing the code in the libraries.

If preventing unexpected exceptions isn't practical, you can exploit the fact that C++ allows you to replace unexpected exceptions with exceptions of a different type. For example, suppose you'd like all unexpected exceptions to be replaced by `UnexpectedException` objects. You can set it up like this,

    class UnexpectedException {};          // all unexpected exception
                                           // objects will be replaced
                                           // by objects of this type

    void convertUnexpected()               // function to call if
    {                                      // an unexpected exception
      throw UnexpectedException();         // is thrown
    }

and make it happen by ``replacing the default `unexpected` function with `convertUnexpected`:

    set_unexpected(convertUnexpected);

Once you've done this, any unexpected exception results in `convertUnexpected` being called. The unexpected exception is then replaced by a new exception of type `UnexpectedException`. Provided the exception specification that was violated includes `UnexpectedException`, exception propagation will then continue as if the exception specification had always been satisfied. (If the exception specification does not include `UnexpectedException`, `terminate` will be called, just as if you had never replaced `unexpected`.)

Another way to translate unexpected exceptions into a well known type is to rely on the fact that if the `unexpected` function's replacement rethrows the current exception, that exception will be replaced by a new exception of the standard type `bad_exception`. Here's how you'd arrange for that to happen:

    void convertUnexpected()          // function to call if
    {                                 // an unexpected exception
      throw;                          // is thrown; just rethrow
    }                                 // the current exception

    set_unexpected(convertUnexpected);
                                      // install convertUnexpected
                                      // as the unexpected
                                      // replacement

If you do this and you include `bad_exception` (or its base class, the standard class `exception`) in all your exception specifications, you'll never have to worry about your program halting if an unexpected exception is encountered. Instead, any wayward exception will be replaced by a `bad_exception`, and that exception will be propagated in the stead of the original one.

By now you understand that exception specifications can be a lot of trouble. Compilers perform only partial checks for their consistent usage, they're problematic in templates, they're easy to violate inadvertently, and, by default, they lead to abrupt program termination when they're violated. Exception specifications have another drawback, too, and that's that they result in `unexpected` being invoked even when a higher-level caller is prepared to cope with the exception that's arisen. For example, consider this code, which is taken almost verbatim from Item 11:

    class Session {                  // for modeling online
    public:                          // sessions
      ~Session();
      ...

    private:
      static void logDestruction(Session *objAddr) throw();
    };

    Session::~Session()
    {
      try {
        logDestruction(this);
      }
      catch (...) {  }
    }

The `Session` destructor calls `logDestruction` to record the fact that a `Session` object is being destroyed, but it explicitly catches any exceptions that might be thrown by `logDestruction`. However, `logDestruction` comes with an exception specification asserting that it throws no exceptions. Now, suppose some function called by `logDestruction` throws an exception that `logDestruction` fails to catch. This isn't supposed to happen, but as we've seen, it isn't difficult to write code that leads to the violation of exception specifications. When this unanticipated exception propagates through `logDestruction`, `unexpected` will be called, and, by default, that will result in termination of the program. This is correct behavior, to be sure, but is it the behavior the author of `Session`'s destructor wanted? That author took pains to handle all possible exceptions, so it seems almost unfair to halt the program without giving `Session`'s destructor's `catch` block a chance to work. If `logDestruction` had no exception specification, this I'm-willing-to-catch-it-if-you'll-just-give-me-a-chance scenario would never arise. (One way to prevent it is to replace `unexpected` as described above.)

It's important to keep a balanced view of exception specifications. They provide excellent documentation on the kinds of exceptions a function is expected to throw, and for situations in which violating an exception specification is so dire as to justify immediate program termination, they offer that behavior by default. At the same time, they are only partly checked by compilers and they are easy to violate inadvertently. Furthermore, they can prevent high-level exception handlers from dealing with unexpected exceptions, even when they know how to. That being the case, exception specifications are a tool to be applied judiciously. Before adding them to your functions, consider whether the behavior they impart to your software is really the behavior you want.

Back to Item 14: Use exception specifications judiciously
Continue to Efficiency

Item 15: Understand the costs of exception handling.

To handle exceptions at runtime, programs must do a fair amount of bookkeeping. At each point during execution, they must be able to identify the objects that require destruction if an exception is thrown; they must make note of each entry to and exit from a `try` block; and for each `try` block, they must keep track of the associated `catch` clauses and the types of exceptions those clauses can handle. This bookkeeping is not free. Nor are the runtime comparisons necessary to ensure that exception specifications are satisfied. Nor is the work expended to destroy the appropriate objects and find the correct `catch` clause when an exception is thrown. No, exception handling has costs, and you pay at least some of them even if you never use the keywords `try`, `throw`, or `catch`.

Let us begin with the things you pay for even if you never use any exception-handling features. You pay for the space used by the data structures needed to keep track of which objects are fully constructed (see Item 10), and you pay for the time needed to keep these data structures up to date. These costs are typically quite modest. Nevertheless, programs compiled without support for exceptions are typically both faster and smaller than their counterparts compiled with support for exceptions.

In theory, you don't have a choice about these costs: exceptions are part of C++, compilers have to support them, and that's that. You can't even expect compiler vendors to eliminate the costs if you use no exception-handling features, because programs are typically composed of multiple independently generated object files, and just because one object file doesn't do anything with exceptions doesn't mean others don't. Furthermore, even if none of the object files linked to form an executable use exceptions, what about the libraries they're linked with? If any part of a program uses exceptions, the rest of the program must support them, too. Otherwise it may not be possible to provide correct exception-handling behavior at runtime.

That's the theory. In practice, most vendors who support exception handling allow you to control whether support for exceptions is included in the code they generate. If you know that no part of your program uses `try`, `throw`, or `catch`, and you also know that no library with which you'll link uses `try`, `throw`, or `catch`, you might as well compile without exception-handling support and save yourself the size and speed penalty you'd otherwise probably be assessed for a feature you're not using. As time goes on and libraries employing exceptions become more common, this strategy will become less tenable, but given the current state of C++ software development, compiling without support for exceptions is a reasonable performance optimization if you have already decided not to use exceptions. It may also be an attractive optimization for libraries that eschew exceptions, provided they can guarantee that exceptions thrown from client code never propagate into the library. This is a difficult guarantee to make, as it precludes client redefinitions of library-declared virtual functions; it also rules out client-defined callback functions.

A second cost of exception-handling arises from `try` blocks, and you pay it whenever you use one, i.e., whenever you decide you want to be able to catch exceptions. Different compilers implement `try` blocks in different ways, so the cost varies from compiler to compiler. As a rough estimate, expect your overall code size to increase by 5-10% and your runtime to go up by a similar amount if you use `try` blocks. This assumes no exceptions are thrown; what we're discussing here is just the cost of having `try` blocks in your programs. To minimize this cost, you should avoid unnecessary `try` blocks.

Compilers tend to generate code for exception specifications much as they do for `try` blocks, so an exception specification generally incurs about the same cost as a `try` block. Excuse me? You say you thought exception specifications were just specifications, you didn't think they generated code? Well, now you have something new to think about.

Which brings us to the heart of the matter, the cost of throwing an exception. In truth, this shouldn't be much of a concern, because exceptions should be rare. After all, they indicate the occurrence of events that are exceptional. The 80-20 rule (see Item 16) tells us that such events should almost never have much impact on a program's overall performance. Nevertheless, I know you're curious about just how big a hit you'll take if you throw an exception, and the answer is it's probably a big one. Compared to a normal function return, returning from a function by throwing an exception may be as much as three orders of magnitude slower. That's quite a hit. But you'll take it only if you throw an exception, and that should be almost never. If, however, you've been thinking of using exceptions to indicate relatively common conditions like the completion of a data structure traversal or the termination of a loop, now would be an excellent time to think again.

But wait. How can I know this stuff? If support for exceptions is a relatively recent addition to most compilers (it is), and if different compilers implement their support in different ways (they do), how can I say that a program's size will generally grow by about 5-10%, its speed will decrease by a similar amount, and it may run orders of magnitude slower if lots of exceptions are thrown? The answer is frightening: a little rumor and a handful of benchmarks (see Item 23). The fact is that most people — including most compiler vendors — have little experience with exceptions, so though we know there are costs associated with them, it is difficult to predict those costs accurately.

The prudent course of action is to be aware of the costs described in this item, but not to take the numbers very seriously. Whatever the cost of exception handling, you don't want to pay any more than you have to. To minimize your exception-related costs, compile without support for exceptions when that is feasible; limit your use of `try` blocks and exception specifications to those locations where you honestly need them; and throw exceptions only under conditions that are truly exceptional. If you still have performance problems, profile your software (see Item 16) to determine if exception support is a contributing factor. If it is, consider switching to different compilers, ones that provide more efficient implementations of C++'s exception-handling features.

Back to Item 14: Use exception specifications judiciously
Continue to Chapter 4: Efficiency

3 A complete version of an almost-standard `auto_ptr` appears on pages 291-294.
Return

4 Now there is. In July 1995, the °ISO/ANSI standardization committee for C++ added a function, `uncaught_exception`, that returns `true` if an exception is active and has not yet been caught.
Return

5 Alas, it can't, at least not portably. Though many compilers accept the code shown on this page, the °standardization committee has inexplicably decreed that "an exception specification shall not appear in a `typedef`." I don't know why. If you need a portable solution, you must — it hurts me to write this — make `CallBackPtr` a macro, sigh.
Return