One of the frequently asked questions in various C++ newsgroups is, "How can I create an object on a pre-determined memory address?" Constructing an object on a previously-allocated memory buffer has many useful applications. For example, a custom garbage collector can use a large pre-allocated memory buffer on which users can construct their objects. When these objects are no longer needed, their storage is automatically reclaimed.
This technique is also useful in time-critical applications. Constructing an object on a pre-allocated buffer is a constant-time operation because the program does not waste precious time on the allocation operation itself. Note also that dynamic memory allocation might fail when the system has insufficient memory. Thus, for mission critical applications, pre-allocating a sufficiently large buffer is sometimes avoidable.
Finally, many applications need to construct a different type of object at a given time (think of a GUI application that displays a different dialog box every time, according to user's input). Instead of using repeated allocations and de-allocations of memory, the application can create in advance a buffer of memory on which a different type of object can be constructed and destroyed cyclically.
C++ provides several features to facilitate the task of constructing an object at a pre-determined memory position. These features include a special form of operator new called placement new, and an explicit destructor invocation. The following demonstrates how this is actually done.
The first step consists of allocating a memory buffer large enough to store an object of the desired type. (If you intend to construct a different type of object every time, you need to allocate a buffer that is at least as large as the largest object). The pre-allocated buffer is a plain char array allocated on the free store:
char * buff = new char [sizeof (Foo) ];
Once you have allocated the buffer, you can construct every type of object on it. For that purpose, you use a special version of operator new, placement new, which takes the address of the pre-allocated buffer as an argument. To use placement new, you have to #include the standard header <new>. In the following code snippet, an object of type Foo is allocated on the memory address of buff using placement new:
#include <new>
Foo * pfoo = new (buff) Foo; //construct a Foo on buff using placement new
Placement new takes the address of a previously allocated buffer and constructs an object of the requested type on that buffer. It returns a pointer to the constructed object. You use this pointer as an ordinary pointer of the requested type:
unsigned int length = pfoo->size();
pfoo->resize(100, 200);
length = pfoo->size();
When the object is not needed anymore, you have to invoke its destructor explicitly. This part is somewhat tricky, because many people falsely assume that the object is destroyed automatically, which it isn't. If you forget to explicitly invoke the destructor before you construct another object on the pre-allocated buffer or before you release the buffer, the program's behavior is undefined. The explicit destructor invocation looks like this:
pfoo->~Foo(); //explicit destructor invocation
In other words, an explicit destructor invocation is similar to an ordinary member function call, except that the name of the member function is the name of the class preceded by a tilde. Once the object has been destroyed, you can use the pre-allocated buffer again to construct another object on it. In fact, this process can be repeated infinitely: You construct an object, destroy it, and recycle the pre-allocated buffer once more.
When the pre-allocated buffer is not needed anymore, or when the application is closed, you have to release the pre-allocated buffer. Recall that you need to use delete[] for that purpose, as the pre-allocated buffer is an array of char. The following snippet contains a complete example of all the steps shown so far, as well as the final release of the buffer:
#include <new>
void placement_demo()
{
char * buff = new char [sizeof (Foo) ]; //1. pre-allocate buffer
Foo * pfoo = new (buff) Foo; //2. use placement new
//use the object
unsigned int length = pfoo->size();
pfoo->resize(100, 200);
//…
pfoo->~Foo(); //3. explicit destructor invocation
delete [] buff; //4. release pre-allocated buffer
}