Logo Data Structures and Algorithms with Object-Oriented Design Patterns in C++
next up previous contents index

C++ Magic

Program gif defines the abstract interface, StoragePool. I.e., given an instance p of a concrete class derived from StoragePool, say SomePool, we can call the member functions like this:

SomePool p;
void* ptr = p.Acquire (100);
// ...
p.Release (ptr);
This code sequence first acquires and subsequently releases a 100-byte area of memory.

What is the relationship between the StoragePool class and the operators new and delete? In a C++ program, the new operator is typically used in a statement of the form

T* tptr = new T;
where T is the name of a type. The new operator creates a new instance of type T and returns a pointer to that instance. This operation involves three distinct steps:
  1. Sufficient storage to hold an instance of type T (i.e., tex2html_wrap_inline68040 bytes) is acquired; and then,
  2. the constructor for T is called to initialize the the object instance; and then,
  3. a pointer to the object is returned.
The C++ compiler accomplishes the first step by calling the function operator new, the prototype of which is:
void* operator new (size_t);
I.e., the function operator new takes an argument that specifies the amount of storage to acquire (in bytes), and returns a pointer to that storage.

Similarly, the statement delete tptr releases the object to which tptr points and returns it to the pool of available storage. This operation involves two distinct steps:

  1. The destructor for object in question is called to finalize the object instance; and then,
  2. the memory locations once occupied by the object are released.
The C++ compiler accomplishes the second step by calling the function operator delete, the prototype of which is:
void operator delete (void*);

The programmer can take over the management of dynamic storage by overloading (or redefining) the functions operator new and operator delete. For example, given an instance p of a concrete class derived from StoragePool, say SomePool, we can overload the functions like this:

SomePool p;

void* operator new (size_t bytes)
    { return p.Acquire (bytes); }

void operator delete (void* vptr)
    { p.Release (vptr); }
In this case, the storage pool is represented by a statically allocated global variable p. All dynamic storage is acquired from and released back to the storage pool p.gif




next up previous contents index

Bruno Copyright © 1997 by Bruno R. Preiss, P.Eng. All rights reserved.