Back to Item 4: Prefer C++-style comments.
Continue to Item 5: Use the same form in corresponding uses of `new` and `delete`.

Memory Management

Memory management concerns in C++ fall into two general camps: getting it right and making it perform efficiently. Good programmers understand that these concerns should be addressed in that order, because a program that is dazzlingly fast and astoundingly small is of little use if it doesn't behave the way it's supposed to. For most programmers, getting things right means calling memory allocation and deallocation routines correctly. Making things perform efficiently, on the other hand, often means writing custom versions of the allocation and deallocation routines. Getting things right there is even more important.

On the correctness front, C++ inherits from C one of its biggest headaches, that of potential memory leaks. Even virtual memory, wonderful invention though it is, is finite, and not everybody has virtual memory in the first place.

In C, a memory leak arises whenever memory allocated through `malloc` is never returned through `free`. The names of the players in C++ are `new` and `delete`, but the story is much the same. However, the situation is improved somewhat by the presence of destructors, because they provide a convenient repository for calls to `delete` that all objects must make when they are destroyed. At the same time, there is more to worry about, because `new` implicitly calls constructors and `delete` implicitly calls destructors. Furthermore, there is the complication that you can define your own versions of `operator` `new` and `operator` `delete`, both inside and outside of classes. This gives rise to all kinds of opportunities to make mistakes. The following Items (as well as Item M8) should help you avoid some of the most common ones.

Back to Memory Management
Continue to Item 6:Use `delete` on pointer members in destructors.

Item 5: Use the same form in corresponding uses of `new` and `delete`.

What's wrong with this picture?

    string *stringArray = new string[100];

    ...

    delete stringArray;

Everything here appears to be in order — the use of `new` is matched with a use of `delete` — but something is still quite wrong: your program's behavior is undefined. At the very least, 99 of the 100 `string` objects pointed to by `stringArray` are unlikely to be properly destroyed, because their destructors will probably never be called.

When you use `new`, two things happen. First, memory is allocated (via the function `operator` `new`, about which I'll have more to say in Items 7-10 as well as Item M8). Second, one or more constructors are called for that memory. When you use `delete`, two other things happen: one or more destructors are called for the memory, then the memory is deallocated (via the function `operator` `delete` — see Items 8 and M8). The big question for `delete` is this: how many objects reside in the memory being deleted? The answer to that determines how many destructors must be called.

Actually, the question is simpler: does the pointer being deleted point to a single object or to an array of objects? The only way for `delete` to know is for you to tell it. If you don't use brackets in your use of `delete`, `delete` assumes a single object is pointed to. Otherwise, it assumes that an array is pointed to:

    string *stringPtr1 = new string;

    string *stringPtr2 = new string[100];

    ...

    delete stringPtr1;           // delete an object

    delete [] stringPtr2;        // delete an array of
                                 // objects

What would happen if you used the "`[]`" form on `stringPtr1`? The result is undefined. What would happen if you didn't use the "`[]`" form on `stringPtr2`? Well, that's undefined too. Furthermore, it's undefined even for built-in types like `int`s, even though such types lack destructors. The rule, then, is simple: if you use `[]` when you call `new`, you must use `[]` when you call `delete`. If you don't use `[]` when you call `new`, don't use `[]` when you call `delete`.

This is a particularly important rule to bear in mind when you are writing a class containing a pointer data member and also offering multiple constructors, because then you've got to be careful to use the same form of `new` in all the constructors to initialize the pointer member. If you don't, how will you know what form of `delete` to use in your destructor? For a further examination of this issue, see Item 11.

This rule is also important for the `typedef`-inclined, because it means that a `typedef`'s author must document which form of `delete` should be employed when `new` is used to conjure up objects of the `typedef` type. For example, consider this `typedef`:

    typedef string AddressLines[4];      // a person's address
                                         // has 4 lines, each of
                                         // which is a string

Because `AddressLines` is an array, this use of `new`,

    string *pal = new AddressLines;      // note that "new
                                         // AddressLines" returns
                                         // a string*, just like
                                         // "new string[4]" would

must be matched with the array form of `delete`:

    delete pal;                          // undefined!

    delete [] pal;                       // fine

To avoid such confusion, you're probably best off abstaining from `typedef`s for array types. That should be easy, however, because the standard C++ library (see Item 49) includes `string` and `vector` templates that reduce the need for built-in arrays to nearly zero. Here, for example, `AddressLines` could be defined to be a `vector` of `string`s. That is, `AddressLines` could be of type `vector<string>`.

Back to Item 5: Use the same form in corresponding uses of `new` and `delete`.
Continue to Item 7: Be prepared for out-of-memory conditions.

Item 6: Use `delete` on pointer members in destructors.

Most of the time, classes performing dynamic memory allocation will use `new` in the constructor(s) to allocate the memory and will later use `delete` in the destructor to free up the memory. This isn't too difficult to get right when you first write the class, provided, of course, that you remember to employ `delete` on all the members that could have been assigned memory in any constructor.

However, the situation becomes more difficult as classes are maintained and enhanced, because the programmers making the modifications to the class may not be the ones who wrote the class in the first place. Under those conditions, it's easy to forget that adding a pointer member almost always requires each of the following:

- Initialization of the pointer in each of the constructors. If no memory is to be allocated to the pointer in a particular constructor, the pointer should be initialized to 0 (i.e., the null pointer).
- Deletion of the existing memory and assignment of new memory in the assignment operator. (See also Item 17.)
- Deletion of the pointer in the destructor.

If you forget to initialize a pointer in a constructor, or if you forget to handle it inside the assignment operator, the problem usually becomes apparent fairly quickly, so in practice those issues don't tend to plague you. Failing to delete the pointer in the destructor, however, often exhibits no obvious external symptoms. Instead, it manifests itself as a subtle memory leak, a slowly growing cancer that will eventually devour your address space and drive your program to an early demise. Because this particular problem doesn't usually call attention to itself, it's important that you keep it in mind whenever you add a pointer member to a class.

Note, by the way, that deleting a null pointer is always safe (it does nothing). Thus, if you write your constructors, your assignment operators, and your other member functions such that each pointer member of the class is always either pointing to valid memory or is null, you can merrily `delete` away in the destructor without regard for whether you ever used `new` for the pointer in question.

There's no reason to get fascist about this Item. For example, you certainly don't want to use `delete` on a pointer that wasn't initialized via `new`, and, except in the case of smart pointer objects (see Item M28), you almost never want to delete a pointer that was passed to you in the first place. In other words, your class destructor usually shouldn't be using `delete` unless your class members were the ones who used `new` in the first place.

Speaking of smart pointers, one way to avoid the need to delete pointer members is to replace those members with smart pointer objects like the standard C++ Library's `auto_ptr`. To see how this can work, take a look at Items M9 and M10.

Back to Item 6: Use delete on pointer members in destructors.
Continue to Item 8: Adhere to convention when writing operator new and operator delete.

Item 7: Be prepared for out-of-memory conditions.

When `operator` `new` can't allocate the memory you request, it throws an exception. (It used to return 0, and some older compilers still do that. You can make your compilers do it again if you want to, but I'll defer that discussion until the end of this Item.) Deep in your heart of hearts, you know that handling out-of-memory exceptions is the only truly moral course of action. At the same time, you are keenly aware of the fact that doing so is a pain in the neck. As a result, chances are that you omit such handling from time to time. Like always, perhaps. Still, you must harbor a lurking sense of guilt. I mean, what if `new` really does yield an exception?

You may think that one reasonable way to cope with this matter is to fall back on your days in the gutter, i.e., to use the preprocessor. For example, a common C idiom is to define a type-independent macro to allocate memory and then check to make sure the allocation succeeded. For C++, such a macro might look something like this:

    #define NEW(PTR, TYPE)                       \
        try { (PTR) = new TYPE; }                \
        catch (std::bad_alloc&) { assert(0); }

("Wait! What's this `std::bad_alloc` business?", you ask. `bad_alloc` is the type of exception `operator` `new` throws when it can't satisfy a memory allocation request, and `std` is the name of the namespace (see Item 28) where `bad_alloc` is defined. "Okay," you continue, "what's this `assert` business?" Well, if you look in the standard C include file `<assert.h>` (or its namespace-savvy C++ equivalent, `<cassert>` — see Item 49), you'll find that `assert` is a macro. The macro checks to see if the expression it's passed is non-zero, and, if it's not, it issues an error message and calls `abort`. Okay, it does that only when the standard macro `NDEBUG` isn't defined, i.e., in debug mode. In production mode, i.e., when `NDEBUG` is defined, `assert` expands to nothing — to a `void` statement. You thus check `assert`ions only when debugging.)

This `NEW` macro suffers from the common error of using an `assert` to test a condition that might occur in production code (after all, you can run out of memory at any time), but it also has a drawback specific to C++: it fails to take into account the myriad ways in which `new` can be used. There are three common syntactic forms for getting new objects of type `T`, and you need to deal with the possibility of exceptions for each of these forms:

    new T;

    new T(constructor arguments);

    new T[size];

This oversimplifies the problem, however, because clients can define their own (overloaded) versions of `operator` `new`, so programs may contain an arbitrary number of different syntactic forms for using `new`.

How, then, to cope? If you're willing to settle for a very simple error-handling strategy, you can set things up so that if a request for memory cannot be satisfied, an error-handling function you specify is called. This strategy relies on the convention that when `operator` `new` cannot satisfy a request, it calls a client-specifiable error-handling function — often called a new-handler — before it throws an exception. (In truth, what `operator` `new` really does is slightly more complicated. Details are provided in Item 8.)

To specify the out-of-memory-handling function, clients call `set_new_handler`, which is specified in the header `<new>` more or less like this:

    typedef void (*new_handler)();
    new_handler set_new_handler(new_handler p) throw();

As you can see, `new_handler` is a typedef for a pointer to a function that takes and returns nothing, and `set_new_handler` is a function that takes and returns a `new_handler`.

`set_new_handler`'s parameter is a pointer to the function `operator` `new` should call if it can't allocate the requested memory. The return value of `set_new_handler` is a pointer to the function in effect for that purpose before `set_new_handler` was called.

You use `set_new_handler` like this:

    // function to call if operator new can't allocate enough memory
    void noMoreMemory()
    {
      cerr << "Unable to satisfy request for memory\n";
      abort();
    }

      int main()
    {
      set_new_handler(noMoreMemory);

      int *pBigDataArray = new int[100000000];

      ...

    }

If, as seems likely, `operator` `new` is unable to allocate space for 100,000,000 integers, `noMoreMemory` will be called, and the program will abort after issuing an error message. This is a marginally better way to terminate the program than a simple core dump. (By the way, consider what happens if memory must be dynamically allocated during the course of writing the error message to `cerr`...)

When `operator` `new` cannot satisfy a request for memory, it calls the new-handler function not once, but repeatedly until it can find enough memory. The code giving rise to these repeated calls is shown in Item 8, but this high-level description is enough to conclude that a well-designed new-handler function must do one of the following:

- Make more memory available. This may allow `operator` `new`'s next attempt to allocate the memory to succeed. One way to implement this strategy is to allocate a large block of memory at program start-up, then release it the first time the new-handler is invoked. Such a release is often accompanied by some kind of warning to the user that memory is low and that future requests may fail unless more memory is somehow made available.
- Install a different new-handler. If the current new-handler can't make any more memory available, perhaps it knows of a different new-handler that is more resourceful. If so, the current new-handler can install the other new-handler in its place (by calling `set_new_handler`). The next time `operator` `new` calls the new-handler function, it will get the one most recently installed. (A variation on this theme is for a new-handler to modify its own behavior, so the next time it's invoked, it does something different. One way to achieve this is to have the new-handler modify static or global data that affects the new-handler's behavior.)
- Deinstall the new-handler, i.e., pass the null pointer to `set_new_handler`. With no new-handler installed, `operator` `new` will throw an exception of type `std::bad_alloc` when its attempt to allocate memory is unsuccessful.
- Throw an exception of type `std::bad_alloc` or some type derived from `std::bad_alloc`. Such exceptions will not be caught by `operator` `new`, so they will propagate to the site originating the request for memory. (Throwing an exception of a different type will violate `operator` `new`'s exception specification. The default action when that happens is to call `abort`, so if your new-handler is going to throw an exception, you definitely want to make sure it's from the `std::bad_alloc` hierarchy. For more information on exception specifications, see Item M14.)
- Not return, typically by calling `abort` or `exit`, both of which are found in the standard C library (and thus in the standard C++ library — see Item 49).

These choices give you considerable flexibility in implementing new-handler functions.

Sometimes you'd like to handle memory allocation failures in different ways, depending on the class of the object being allocated:

    class X {
    public:
      static void outOfMemory();

      ...

    };

    class Y {
    public:
      static void outOfMemory();

      ...

    };

    X* p1 = new X;      // if allocation is unsuccessful,
                        // call X::outOfMemory

    Y* p2 = new Y;      // if allocation is unsuccessful,
                        // call Y::outOfMemory

C++ has no support for class-specific new-handlers, but it doesn't need to. You can implement this behavior yourself. You just have each class provide its own versions of `set_new_handler` and `operator` `new`. The class's `set_new_handler` allows clients to specify the new-handler for the class (just like the standard `set_new_handler` allows clients to specify the global new-handler). The class's `operator` `new` ensures that the class-specific new-handler is used in place of the global new-handler when memory for class objects is allocated.

Consider a class `X` for which you want to handle memory allocation failures. You'll have to keep track of the function to call when `operator` `new` can't allocate enough memory for an object of type `X`, so you'll declare a static member of type `new_handler` to point to the new-handler function for the class. Your class `X` will look something like this:

    class X {
    public:
      static new_handler set_new_handler(new_handler p);
      static void * operator new(size_t size);

    private:
      static new_handler currentHandler;
    };

Static class members must be defined outside the class definition. Because you'll want to use the default initialization of static objects to 0, you'll define `X::currentHandler` without initializing it:

    new_handler X::currentHandler;      // sets currentHandler
                                        // to 0 (i.e., null) by
                                        // default

The `set_new_handler` function in class `X` will save whatever pointer is passed to it. It will return whatever pointer had been saved prior to the call. This is exactly what the standard version of `set_new_handler` does:

    new_handler X::set_new_handler(new_handler p)
    {
      new_handler oldHandler = currentHandler;
      currentHandler = p;
      return oldHandler;
    }

Finally, `X`'s `operator` `new` will do the following:

1. Call the standard `set_new_handler` with `X`'s error-handling function. This will install `X`'s new-handler as the global new- handler. In the code below, notice how you explicitly reference the `std` scope (where the standard `set_new_handler` resides) by using the "`::`" notation.
2. Call the global `operator` `new` to actually allocate the requested memory. If the initial attempt at allocation fails, the global `operator` `new` will invoke `X`'s new-handler, because that function was just installed as the global new-handler. If the global `operator` `new` is ultimately unable to find a way to allocate the requested memory, it will throw a `std::bad_alloc` exception, which `X`'s `operator` `new` will catch. `X`'s `operator` `new` will then restore the global new-handler that was originally in place, and it will return by propagating the exception.
3. Assuming the global `operator` `new` was able to successfully allocate enough memory for an object of type `X`, `X`'s `operator` `new` will again call the standard `set_new_handler` to restore the global error-handling function to what it was originally. It will then return a pointer to the allocated memory.

Here's how you say all that in C++:

    void * X::operator new(size_t size)
    {
      new_handler globalHandler =                // install X's
        std::set_new_handler(currentHandler);    // handler

      void *memory;

      try {                                      // attempt
        memory = ::operator new(size);           // allocation
      }
      catch (std::bad_alloc&) {                  // restore
        std::set_new_handler(globalHandler);     // handler;
        throw;                                   // propagate
      }                                          // exception

      std::set_new_handler(globalHandler);       // restore
                                                 // handler
      return memory;
    }

If the duplicated calls to `std::set_new_handler` caught your eye, turn to Item M9 for information on how to eliminate them.

Clients of class `X` use its new-handling capabilities like this:

    void noMoreMemory();                           // decl. of function to
                                                   // call if memory allocation
                                                   // for X objects fails

    X::set_new_handler(noMoreMemory);
                                                   // set noMoreMemory as X's
                                                   // new-handling function

    X *px1 = new X;                                // if memory allocation
                                                   // fails, call noMoreMemory

    string *ps = new string;                       // if memory allocation
                                                   // fails, call the global
                                                   // new-handling function
                                                   // (if there is one)

    X::set_new_handler(0);                         // set the X-specific
                                                   // new-handling function
                                                   // to nothing (i.e., null)

    X *px2 = new X;                                // if memory allocation
                                                   // fails, throw an exception
                                                   // immediately. (There is
                                                   // no new-handling function
                                                   // for class X.)

You may note that the code for implementing this scheme is the same regardless of the class, so a reasonable inclination would be to reuse it in other places. As Item 41 explains, both inheritance and templates can be used to create reusable code. However, in this case, it's a combination of the two that gives you what you need.

All you have to do is create a "mixin-style" base class, i.e., a base class that's designed to allow derived classes to inherit a single specific capability — in this case, the ability to set a class-specific new-handler. Then you turn the base class into a template. The base class part of the design lets derived classes inherit the `set_new_handler` and `operator` `new` functions they all need, while the template part of the design ensures that each inheriting class gets a different `currentHandler` data member. The result may sound a little complicated, but you'll find that the code looks reassuringly familiar. In fact, about the only real difference is that it's now reusable by any class that wants it:

    template<class T>				// "mixin-style" base class
    class NewHandlerSupport {			// for class-specific
    public:						// set_new_handler support

      static new_handler set_new_handler(new_handler p);
      static void * operator new(size_t size);

    private:
      static new_handler currentHandler;
    };

    template<class T>
    new_handler NewHandlerSupport<T>::set_new_handler(new_handler p)
    {
      new_handler oldHandler = currentHandler;
      currentHandler = p;
      return oldHandler;
    }

    template<class T>
    void * NewHandlerSupport<T>::operator new(size_t size)
    {
      new_handler globalHandler =
        std::set_new_handler(currentHandler);

      void *memory;

      try {
        memory = ::operator new(size);
      }
      catch (std::bad_alloc&) {
        std::set_new_handler(globalHandler);
        throw;
      }

      std::set_new_handler(globalHandler);

      return memory;
    }

    // this sets each currentHandler to 0
    template<class T>
    new_handler NewHandlerSupport<T>::currentHandler;

With this class template, adding `set_new_handler` support to class `X` is easy: `X` just inherits from `newHandlerSupport<X>`:

    // note inheritance from mixin base class template. (See
    // my article on counting objects for information on why
    // private inheritance might be preferable here.)
    class X: public NewHandlerSupport<X> {

      ...                 // as before, but no declarations for
    };                    // set_new_handler or operator new

Clients of `X` remain oblivious to all the behind-the-scenes action; their old code continues to work. This is good, because one thing you can usually rely on your clients being is oblivious.

Using `set_new_handler` is a convenient, easy way to cope with the possibility of out-of-memory conditions. Certainly it's a lot more attractive than wrapping every use of `new` inside a `try` block. Furthermore, templates like `NewHandlerSupport` make it simple to add a class-specific new-handler to any class that wants one. Mixin-style inheritance, however, invariably leads to the topic of multiple inheritance, and before starting down that slippery slope, you'll definitely want to read Item 43.

Until 1993, C++ required that `operator` `new` return 0 when it was unable to satisfy a memory request. The current behavior is for `operator` `new` to throw a `std::bad_alloc` exception, but a lot of C++ was written before compilers began supporting the revised specification. The °C++ standardization committee didn't want to abandon the established test-for-0 code base, so they provided alternative forms of `operator` `new` (and `operator` `new[]` — see Item 8) that continue to offer the traditional failure-yields-0 behavior. These forms are called "nothrow" forms because, well, they never do a `throw`, and they employ `nothrow` objects (defined in the standard header `<new>`) at the point where `new` is used:

    class Widget { ... };

    Widget *pw1 = new Widget;      // throws std::bad_alloc if
                                   // allocation fails

    if (pw1 == 0) ...              // this test must fail

    Widget *pw2 =
      new (nothrow) Widget;        // returns 0 if allocation
                                   // fails

    if (pw2 == 0) ...              // this test may succeed

Regardless of whether you use "normal" (i.e., exception-throwing) `new` or "nothrow" `new`, it's important that you be prepared to handle memory allocation failures. The easiest way to do that is to take advantage of `set_new_handler`, because it works with both forms.

Back to Item 7: Be prepared for out-of-memory conditions.
Continue to Item 9: Avoid hiding the "normal" form of new.

Item 8: Adhere to convention when writing `operator` `new` and `operator` `delete`.

When you take it upon yourself to write `operator` `new` (Item 10 explains why you might want to), it's important that your function(s) offer behavior that is consistent with the default `operator` `new`. In practical terms, this means having the right return value, calling an error-handling function when insufficient memory is available (see Item 7), and being prepared to cope with requests for no memory. You also need to avoid inadvertently hiding the "normal" form of `new`, but that's a topic for Item 9.

The return value part is easy. If you can supply the requested memory, you just return a pointer to it. If you can't, you follow the rule described in Item 7 and throw an exception of type `std::bad_alloc`.

It's not quite that simple, however, because `operator` `new` actually tries to allocate memory more than once, calling the error-handling function after each failure, the assumption being that the error-handling function might be able to do something to free up some memory. Only when the pointer to the error-handling function is null does `operator` `new` throw an exception.

In addition, the °C++ standard requires that `operator` `new` return a legitimate pointer even when 0 bytes are requested. (Believe it or not, requiring this odd-sounding behavior actually simplifies things elsewhere in the language.)

That being the case, pseudocode for a non-member `operator` `new` looks like this:

    void * operator new(size_t size)        // your operator new might
    {                                       // take additional params

      if (size == 0) {                      // handle 0-byte requests
        size = 1;                           // by treating them as
      }                                     // 1-byte requests

      while (1) {
        attempt to allocate size bytes;

        if (the allocation was successful)
          return (a pointer to the memory);

        // allocation was unsuccessful; find out what the
        // current error-handling function is (see Item 7)
        new_handler globalHandler = set_new_handler(0);
        set_new_handler(globalHandler);

        if (globalHandler) (*globalHandler)();
        elsethrow std::bad_alloc();
      }
    }

The trick of treating requests for zero bytes as if they were really requests for one byte looks slimy, but it's simple, it's legal, it works, and how often do you expect to be asked for zero bytes, anyway?

You may also look askance at the place in the pseudocode where the error-handling function pointer is set to null, then promptly reset to what it was originally. Unfortunately, there is no way to get at the error-handling function pointer directly, so you have to call `set_new_handler` to find out what it is. Crude, yes, but also effective.

Item 7 remarks that `operator` `new` contains an infinite loop, and the code above shows that loop explicitly — `while` `(1)` is about as infinite as it gets. The only way out of the loop is for memory to be successfully allocated or for the new-handling function to do one of the things described in Item 7: make more memory available, install a different new-handler, deinstall the new-handler, throw an exception of or derived from `std::bad_alloc`, or fail to return. It should now be clear why the new-handler must do one of those things. If it doesn't, the loop inside `operator` `new` will never terminate.

One of the things many people don't realize about `operator` `new` is that it's inherited by subclasses. That can lead to some interesting complications. In the pseudocode for `operator` `new` above, notice that the function tries to allocate `size` bytes (unless `size` is 0). That makes perfect sense, because that's the argument that was passed to the function. However, most class-specific versions of `operator` `new` (including the one you'll find in Item 10) are designed for a specific class, not for a class or any of its subclasses. That is, given an `operator` `new` for a class `X`, the behavior of that function is almost always carefully tuned for objects of size `sizeof(X)` — nothing larger and nothing smaller. Because of inheritance, however, it is possible that the `operator` `new` in a base class will be called to allocate memory for an object of a derived class:

    class Base {
    public:
      static void * operator new(size_t size);
      ...
    };

    class Derived: public Base       // Derived doesn't declare
    { ... };                         // operator new

    Derived *p = new Derived;        // calls Base::operator new!

If `Base`'s class-specific `operator` `new` wasn't designed to cope with this — and chances are slim that it was — the best way for it to handle the situation is to slough off calls requesting the "wrong" amount of memory to the standard `operator` `new`, like this:

    void * Base::operator new(size_t size)
    {
      if (size != sizeof(Base))             // if size is "wrong,"
        return ::operator new(size);        // have standard operator
                                            // new handle the request

      ...                                   // otherwise handle
                                            // the request here
    }

"Hold on!" I hear you cry, "You forgot to check for the pathological-but-nevertheless-possible case where `size` is zero!" Actually, I didn't, and please stop using hyphens when you cry out. The test is still there, it's just been incorporated into the test of `size` against `sizeof(Base)`. The °C++ standard works in mysterious ways, and one of those ways is to decree that all freestanding classes have nonzero size. By definition, `sizeof(Base)` can never be zero (even if it has no members), so if `size` is zero, the request will be forwarded to `::operator` `new`, and it will become that function's responsibility to treat the request in a reasonable fashion. (Interestingly, `sizeof(Base)` may be zero if `Base` is not a freestanding class. For details, consult my article on counting objects.)

If you'd like to control memory allocation for arrays on a per-class basis, you need to implement `operator` `new`'s array-specific cousin, `operator` `new[]`. (This function is usually called "array new," because it's hard to figure out how to pronounce "operator new[]".) If you decide to write `operator` `new[]`, remember that all you're doing is allocating raw memory — you can't do anything to the as-yet-nonexistent objects in the array. In fact, you can't even figure out how many objects will be in the array, because you don't know how big each object is. After all, a base class's `operator` `new[]` might, through inheritance, be called to allocate memory for an array of derived class objects, and derived class objects are usually bigger than base class objects. Hence, you can't assume inside `Base::operator` `new[]` that the size of each object going into the array is `sizeof(Base)`, and that means you can't assume that the number of objects in the array is `(``bytes` `requested``)/sizeof(Base)`. For more information on `operator` `new[]`, see Item M8.

So much for the conventions you need to follow when writing `operator` `new` (and `operator` `new[]`). For `operator` `delete` (and its array counterpart, `operator` `delete[]`), things are simpler. About all you need to remember is that C++ guarantees it's always safe to delete the null pointer, so you need to honor that guarantee. Here's pseudocode for a non-member `operator delete`:

    void operator delete(void *rawMemory)
    {
      if (rawMemory == 0) return;    // do nothing if the null
                                     // pointer is being deleted

      deallocate the memory pointed to by rawMemory;

      return;
    }

The member version of this function is simple, too, except you've got to be sure to check the size of what's being deleted. Assuming your class-specific `operator` `new` forwards requests of the "wrong" size to `::operator` `new`, you've got to forward "wrongly sized" deletion requests to `::operator` `delete`:

    class Base {                       // same as before, but now
    public:                            // op. delete is declared
      static void * operator new(size_t size);
      static void operator delete(void *rawMemory, size_t size);
      ...
    };

    void Base::operator delete(void *rawMemory, size_t size)
    {
      if (rawMemory == 0) return;      // check for null pointer

      if (size != sizeof(Base)) {      // if size is "wrong,"
        ::operator delete(rawMemory);  // have standard operator
        return;                        // delete handle the request
      }

      deallocate the memory pointed to by rawMemory;

      return;
    }

The conventions, then, for `operator` `new` and `operator` `delete` (and their array counterparts) are not particularly onerous, but it is important that you obey them. If your allocation routines support new-handler functions and correctly deal with zero-sized requests, you're all but finished, and if your deallocation routines cope with null pointers, there's little more to do. Add support for inheritance in member versions of the functions, and presto! — you're done.

Back to Item 8: Adhere to convention when writing operator new and operator delete.
Continue to Item 10: Write operator delete if you write operator new.

Item 9: Avoid hiding the "normal" form of `new`.

A declaration of a name in an inner scope hides the same name in outer scopes, so for a function `f` at both global and class scope, the member function will hide the global function:

    void f();                             // global function

    class X {
    public:
      void f();                           // member function
    };

    X x;

    f();                                  // calls global f

    x.f();                                // calls X::f

This is unsurprising and normally causes no confusion, because global and member functions are usually invoked using different syntactic forms. However, if you add to this class an `operator` `new` taking additional parameters, the result is likely to be an eye-opener:

    class X {
    public:
      void f();

      // operator new allowing specification of a
      // new-handling function
      static void * operator new(size_t size, new_handler p);
    };

    void specialErrorHandler();          // definition is elsewhere

    X *px1 =
      new (specialErrorHandler) X;       // calls X::operator new

    X *px2 = new X;                      // error!

By declaring a function called "operator new" inside the class, you inadvertently block access to the "normal" form of `new`. Why this is so is discussed in Item 50. Here we're more interested in figuring out how to avoid the problem.

One solution is to write a class-specific `operator` `new` that supports the "normal" invocation form. If it does the same thing as the global version, that can be efficiently and elegantly encapsulated as an inline function:

    class X {
    public:
      void f();

      static void * operator new(size_t size, new_handler p);

      static void * operator new(size_t size)
      { return ::operator new(size); }
    };

    X *px1 =
      new (specialErrorHandler) X;      // calls X::operator
                                        // new(size_t, new_handler)

    X* px2 = new X;                     // calls X::operator
                                        // new(size_t)

An alternative is to provide a default parameter value (see Item 24) for each additional parameter you add to `operator` `new`:

    class X {
    public:
      void f();

      static
        void * operator new(size_t size,                // note default
                            new_handler p = 0);         // value for p
    };

    X *px1 = new (specialErrorHandler) X;               // fine

    X* px2 = new X;                                     // also fine

Either way, if you later decide to customize the behavior of the "normal" form of `new`, all you need to do is rewrite the function; callers will get the customized behavior automatically when they relink.

Back to Item 9: Avoid hiding the "normal" form of new.
Continue to Constructors, Destructors, and Assignment Operators

Item 10: Write `operator` `delete` if you write `operator` `new`.

Let's step back for a moment and return to fundamentals. Why would anybody want to write their own version of `operator` `new` or `operator` `delete` in the first place?

More often than not, the answer is efficiency. The default versions of `operator` `new` and `operator` `delete` are perfectly adequate for general-purpose use, but their flexibility inevitably leaves room for improvements in their performance in a more circumscribed context. This is especially true for applications that dynamically allocate a large number of small objects.

As an example, consider a class for representing airplanes, where the `Airplane` class contains only a pointer to the actual representation for airplane objects (a technique discussed in Item 34):

    class AirplaneRep { ... };      // representation for an
                                    // Airplane object
    class Airplane {
    public:
      ...
    private:
      AirplaneRep *rep;             // pointer to representation
    };

An `Airplane` object is not very big; it contains but a single pointer. (As explained in Items 14 and M24, it may implicitly contain a second pointer if the `Airplane` class declares virtual functions.) When you allocate an `Airplane` object by calling `operator` `new`, however, you probably get back more memory than is needed to store this pointer (or pair of pointers). The reason for this seemingly wayward behavior has to do with the need for `operator` `new` and `operator` `delete` to communicate with one another.

Because the default version of `operator` `new` is a general-purpose allocator, it must be prepared to allocate blocks of any size. Similarly, the default version of `operator` `delete` must be prepared to deallocate blocks of whatever size `operator` `new` allocated. For `operator` `delete` to know how much memory to deallocate, it must have some way of knowing how much memory `operator` `new` allocated in the first place. A common way for `operator` `new` to tell `operator` `delete` how much memory it allocated is by prepending to the memory it returns some additional data that specifies the size of the allocated block. That is, when you say this,

    Airplane *pa = new Airplane;

you don't necessarily get back a block of memory that looks like this:

Instead, you often get back a block of memory that looks more like this:

For small objects like those of class `Airplane`, this additional bookkeeping data can more than double the amount of memory needed for each dynamically allocated object (especially if the class contains no virtual functions).

If you're developing software for an environment in which memory is precious, you may not be able to afford this kind of spendthrift allocation. By writing your own `operator` `new` for the `Airplane` class, you can take advantage of the fact that all `Airplane` objects are the same size, so there isn't any need for bookkeeping information to be kept with each allocated block.

One way to implement your class-specific `operator` `new` is to ask the default `operator` `new` for big blocks of raw memory, each block of sufficient size to hold a large number of `Airplane` objects. The memory chunks for `Airplane` objects themselves will be taken from these big blocks. Currently unused chunks will be organized into a linked list — the free list — of chunks that are available for future `Airplane` use. This may make it sound like you'll have to pay for the overhead of a `next` field in every object (to support the list), but you won't: the space for the `rep` field (which is necessary only for memory chunks in use as `Airplane` objects) will also serve as the place to store the `next` pointer (because that pointer is needed only for chunks of memory not in use as `Airplane` objects). You'll arrange for this job-sharing in the usual fashion: you'll use a `union`.

To turn this design into reality, you have to modify the definition of `Airplane` to support custom memory management. You do it as follows:

    class Airplane {           // modified class — now supports
    public:                    // custom memory management

      static void * operator new(size_t size);

      ...

    private:
      union {
        AirplaneRep *rep;      // for objects in use
        Airplane *next;        // for objects on free list
      };

      // this class-specific constant (see Item 1) specifies how
      // many Airplane objects fit into a big memory block;
      // it's initialized below
      static const int BLOCK_SIZE;

      static Airplane *headOfFreeList;

    };

Here you've added the declarations for `operator` `new`, the union that allows the `rep` and `next` fields to occupy the same memory, a class-specific constant for specifying how big each allocated block should be, and a static pointer to keep track of the head of the free list. It's important to use a static member for this last task, because there's one free list for the entire class, not one free list for each `Airplane` object.

The next thing to do is to write the new `operator` `new`:

    void * Airplane::operator new(size_t size)
    {
      // send requests of the "wrong" size to ::operator new();
      // for details, see Item 8
      if (size != sizeof(Airplane))
        return ::operator new(size);

      Airplane *p =           // p is now a pointer to the
        headOfFreeList;       // head of the free list

      // if p is valid, just move the list head to the
      // next element in the free list
      if (p)
        headOfFreeList = p->next;

      else {
        // The free list is empty. Allocate a block of memory
        // big enough to hold BLOCK_SIZE Airplane objects
        Airplane *newBlock =
          static_cast<Airplane*>(::operator new(BLOCK_SIZE *
                                                sizeof(Airplane)));

        // form a new free list by linking the memory chunks
        // together; skip the zeroth element, because you'll
        // return that to the caller of operator new
        for (int i = 1; i < BLOCK_SIZE-1; ++i)
          newBlock[i].next = &newBlock[i+1];

        // terminate the linked list with a null pointer
        newBlock[BLOCK_SIZE-1].next = 0;

        // set p to front of list, headOfFreeList to
        // chunk immediately following
        p = newBlock;
        headOfFreeList = &newBlock[1];
      }

      return p;
    }

If you've read Item 8, you know that when `operator` `new` can't satisfy a request for memory, it's supposed to perform a series of ritualistic steps involving new-handler functions and exceptions. There is no sign of such steps above. That's because this `operator` `new` gets all the memory it manages from `::operator` `new`. That means this `operator` `new` can fail only if `::operator` `new` does. But if `::operator` `new` fails, it must engage in the new-handling ritual (possibly culminating in the throwing of an exception), so there is no need for `Airplane`'s `operator` `new` to do it, too. In other words, the new-handler behavior is there, you just don't see it, because it's hidden inside `::operator` `new`.

Given this `operator` `new`, the only thing left to do is provide the obligatory definitions of `Airplane`'s static data members:

    Airplane *Airplane::headOfFreeList;         // these definitions
                                                // go in an implemen-
    const int Airplane::BLOCK_SIZE = 512;       // tation file, not
                                                // a header file

There's no need to explicitly set `headOfFreeList` to the null pointer, because static members are initialized to 0 by default. The value for `BLOCK_SIZE`, of course, determines the size of each memory block we get from `::operator` `new`.

This version of `operator` `new` will work just fine. Not only will it use a lot less memory for `Airplane` objects than the default `operator` `new`, it's also likely to be faster, possibly as much as two orders of magnitude faster. That shouldn't be surprising. After all, the general version of `operator` `new` has to cope with memory requests of different sizes, has to worry about internal and external fragmentation, etc., whereas your version of `operator` `new` just manipulates a couple of pointers in a linked list. It's easy to be fast when you don't have to be flexible.

At long last we are in a position to discuss `operator` `delete`. Remember `operator` `delete`? This Item is about `operator` `delete`. As currently written, your `Airplane` class declares `operator` `new`, but it does not declare `operator` `delete`. Now consider what happens when a client writes the following, which is nothing if not eminently reasonable:

    Airplane *pa = new Airplane;        // calls
                                        // Airplane::operator new
    ...

    delete pa;                          // calls ::operator delete

If you listen closely when you read this code, you can hear the sound of an airplane crashing and burning, with much weeping and wailing by the programmers who knew it. The problem is that `operator` `new` (the one defined in `Airplane`) returns a pointer to memory without any header information, but `operator` `delete` (the default, global one) assumes that the memory it's passed does contain header information! Surely this is a recipe for disaster.

This example illustrates the general rule: `operator` `new` and `operator` `delete` must be written in concert so that they share the same assumptions. If you're going to roll your own memory allocation routine, be sure to roll one for deallocation, too. (For another reason why you should follow this advice, turn to the sidebar on placement `new` and placement `delete` in my article on counting objects in C++.)

Here's how you solve the problem with the `Airplane` class:

    class Airplane {        // same as before, except there's
    public:                 // now a decl. for operator delete
      ...

    static void operator delete(void *deadObject,
                                size_t size);

    };

    // operator delete is passed a memory chunk, which,
    // if it's the right size, is just added to the
    // front of the list of free chunks
    void Airplane::operator delete(void *deadObject,
                                   size_t size)
    {
      if (deadObject == 0) return;         // see Item 8

      if (size != sizeof(Airplane))     {  // see Item 8
        ::operator delete(deadObject);
        return;
      }

      Airplane *carcass =
        static_cast<Airplane*>(deadObject);

      carcass->next = headOfFreeList;
      headOfFreeList = carcass;
    }

Because you were careful in `operator` `new` to ensure that calls of the "wrong" size were forwarded to the global `operator` `new` (see Item 8), you must demonstrate equal care in ensuring that such "improperly sized" objects are handled by the global version of `operator` `delete`. If you did not, you'd run into precisely the problem you have been laboring so arduously to avoid — a semantic mismatch between `new` and `delete`.

Interestingly, the `size_t` value C++ passes to `operator` `delete` may be incorrect if the object being deleted was derived from a base class lacking a virtual destructor. This is reason enough for making sure your base classes have virtual destructors, but Item 14 describes a second, arguably better reason. For now, simply note that if you omit virtual destructors in base classes, `operator` `delete` functions may not work correctly.

All of which is well and good, but I can tell by the furrow in your brow that what you're really concerned about is the memory leak. With all the software development experience you bring to the table, there's no way you'd fail to notice that `Airplane`'s `operator` `new` calls `::operator` `new` to get big blocks of memory, but Airplane's `operator` `delete` fails to release those blocks.4 Memory leak! Memory leak! I can almost hear the alarm bells going off in your head.

Listen to me carefully: there is no memory leak.

A memory leak arises when memory is allocated, then all pointers to that memory are lost. Absent garbage collection or some other extralinguistic mechanism, such memory cannot be reclaimed. But this design has no memory leak, because it's never the case that all pointers to memory are lost. Each big block of memory is first broken down into `Airplane`-sized chunks, and these chunks are then placed on the free list. When clients call `Airplane::operator` `new`, chunks are removed from the free list, and clients receive pointers to them. When clients call `operator` `delete`, the chunks are put back on the free list. With this design, all memory chunks are either in use as `Airplane` objects (in which case it's the clients' responsibility to avoid leaking their memory) or are on the free list (in which case there's a pointer to the memory). There is no memory leak.

Nevertheless, the blocks of memory returned by `::operator` `new` are never released by `Airplane::operator` `delete`, and there has to be some name for that. There is. You've created a memory pool. Call it semantic gymnastics if you must, but there is an important difference between a memory leak and a memory pool. A memory leak may grow indefinitely, even if clients are well-behaved, but a memory pool never grows larger than the maximum amount of memory requested by its clients.

It would not be difficult to modify `Airplane`'s memory management routines so that the blocks of memory returned by `::operator` `new` were automatically released when they were no longer in use, but there are two reasons why you might not want to do it.

The first concerns your likely motivation for tackling custom memory management. There are many reasons why you might do it, but the most common one is that you've determined (see Item M16) that the default `operator` `new` and `operator` `delete` use too much memory or are too slow (or both). That being the case, every additional byte and every additional statement you devote to tracking and releasing those big memory blocks comes straight off the bottom line: your software runs slower and uses more memory than it would if you adopted the pool strategy. For libraries and applications in which performance is at a premium and you can expect pool sizes to be reasonably bounded, the pool approach may well be best.

The second reason has to do with pathological behavior. Suppose `Airplane`'s memory management routines are modified so `Airplane`'s `operator` `delete` releases any big block of memory that has no active objects in it. Now consider this program:

    int main()
    {
      Airplane *pa = new Airplane;     // first allocation: get big
                                       // block, make free list, etc.

      delete pa;                       // block is now empty;
                                       // release it

      pa = new Airplane;               // uh oh, get block again,
                                       // make free list, etc.

      delete pa;                       // okay, block is empty
                                       // again; release it

      ...                              // you get the idea...

      return 0;
    }

This nasty little program will run slower and use more memory than with even the default `operator` `new` and `operator` `delete`, much less the pool-based versions of those functions!

Of course, there are ways to deal with this pathology, but the more you code for uncommon special cases, the closer you get to reimplementing the default memory management functions, and then what have you gained? A memory pool is not the answer to all memory management questions, but it's a reasonable answer to many of them.

In fact, it's a reasonable answer often enough that you may be bothered by the need to reimplement it for different classes. "Surely," you think to yourself, "there should be a way to package the notion of a fixed-sized memory allocator so it's easily reused." There is, though this Item has droned on long enough that I'll leave the details in the form of the dreaded exercise for the reader.

Instead, I'll simply show a minimal interface (see Item 18) to a `Pool` class, where each object of type `Pool` is an allocator for objects of the size specified in the `Pool`'s constructor:

    class Pool {
    public:
      Pool(size_t n);                      // Create an allocator for
                                           // objects of size n

      void * alloc(size_t n)  ;            // Allocate enough memory
                                           // for one object; follow
                                           // operator new conventions
                                           // from Item 8

      void free(  void *p, size_t n);      // Return to the pool the
                                           // memory pointed to by p;
                                           // follow operator delete
                                           // conventions from Item 8

      ~Pool();                             // Deallocate all memory in
                                           // the pool
    };

This class allows `Pool` objects to be created, to perform allocation and deallocation operations, and to be destroyed. When a `Pool` object is destroyed, it releases all the memory it allocated. This means there is now a way to avoid the memory leak-like behavior that `Airplane`'s functions exhibited. However, this also means that if a `Pool`'s destructor is called too soon (before all the objects using its memory have been destroyed), some objects will find their memory yanked out from under them before they're done using it. To say that the resulting behavior is undefined is being generous.

Given this `Pool` class, even a Java programmer can add custom memory management capabilities to `Airplane` without breaking a sweat:

    class Airplane {
    public:

      ...                               // usual Airplane functions

      static void * operator new(size_t size);
      static void operator delete(void *p, size_t size);

    private:
      AirplaneRep *rep;                 // pointer to representation
      static Pool memPool;              // memory pool for Airplanes

    };

    inline void * Airplane::operator new(size_t size)
    { return memPool.alloc(size); }

    inline void Airplane::operator delete(void *p,
                                          size_t size)
    { memPool.free(p, size); }

    // create a new pool for Airplane objects; this goes in
    // the class implementation file
    Pool Airplane::memPool(sizeof(Airplane));

This is a much cleaner design than the one we saw earlier, because the `Airplane` class is no longer cluttered with non-airplane details. Gone are the `union`, the head of the free list, the constant defining how big each raw memory block should be, etc. That's all hidden inside `Pool`, which is really where it should be. Let `Pool`'s author worry about memory management minutiae. Your job is to make the `Airplane` class work properly.

Now, it's interesting to see how custom memory management routines can improve program performance, and it's worthwhile to see how such routines can be encapsulated inside a class like `Pool`, but let us not lose sight of the main point. That point is that `operator` `new` and `operator` `delete` need to work together, so if you write `operator` `new`, be sure to write `operator` `delete`, as well.

Back to Item 10: Write operator delete if you write operator new.
Continue to Constructors, Destructors, and Assignment Operators

4 I write this with certainty, because I failed to address this issue in the first edition of this book, and many readers upbraided me for the omission. There's nothing quite like a few thousand proofreaders to demonstrate one's fallibility, sigh.
Return