Ask the C++ Pro 10-Minute Solutions

Constructing an Object at a Pre-Determined Memory Position
By Danny Kalev

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
  }

 
Other 10-Minute Solutions
 How to Change the Mouse Pointer without Flicker
 Setting Full Row Selection in ListView Control
 Automating Type Conversions with stringstream Objects
 Improving Memory Reallocation with Vectors
 How to Use <fstream> Classes for File I/O
 Casting About for Safe Typecasting
 Overloading Operator + the Right Way
 How to Create Persistent Objects
 Making Linked Lists More User-Friendly
 Preventing Glitches in Signal Processing
 Forcing Object Allocation on the Free-store
 Using String-Based Data Validation
 Implementing the 'Resource Acquisition Is Initialization' Idiom
 Simple Locks for Data Files
 Template Specializations
 Exception Handling
 Using Bit Fields in Data Optimization
 Using the Transform() Algorithm to Change a String's Case
 Use RTTI for Dynamic Type Identification
 Choosing the Right swap () Implementation
 Take Charge and Initialize Your Own Data
 Share Data Among Objects Using the Monostate Design Pattern
 String Manipulation Made Easy with std::string Algorithms
 Using typedef to Curb Miscreant Code
 Managing Objects' Construction Order
 Bitwise Operators: Combining Efficiency and Ease of Use
 Use Function Adapters to Extend Generic Algorithms' Usage
 Simplify Callback Dispatching with Enumerated Indexes
 Streamline Your Bulk I/O Operations with Stream Iterators
 Optimize Your Member Layout
 Preserve Code Safety with Conversion Operators
 Modify Your Base Class Interface in Derived Classes
 Tackle Common Programming Tasks Using the New <tuple> Library
 Use Local Classes for Proper Cleanup in Exception-enabled Apps
 Use multimap to Create Associative Containers with Duplicate Keys
 Enforcing Compile-time Constraints
 Facilitate Directory Operations with the <dirent.h> and <dir.h> Libraries
 Spruce Up Your Built-in Arrays
 Target 32- and 64-bit Platforms Together with a Few Simple Datatype Changes
 Restrict Object Allocation to Specific Memory Types
 Use the Pimpl Idiom to Reduce Compilation Time and Enhance Encapsulation
 Automate Resource Management with shared_ptr
 The Quick and Dirty Way to Add
 Pointing to Class Members
 Detecting Keystrokes While Your Application is Busy
 Linked Lists
 Programming the System Tray
 Create a "Universal" DLL
 Convert Path to Long Path Name
 Constructing an Object at a Pre-Determined Memory Position
 Declaring Classes and Member Functions in a Namespace
 Using the auto_ptr Class Template to Facilitate Dynamic Memory Management
 Using the random_shuffle() Algorithm to Randomize a Sequence of Elements
 Defining a Function Object
 Implementing the Singleton Design Pattern
 Declaring Function Pointers and Implementing Callbacks
 Overloading Operator << for a User-Defined Type
 Implementing a Stopwatch Class for Performance Measurements
 Creating and Accessing Environment Variables
 Executing an Object's Member Function in a Separate Thread
 Creating Heterogeneous Containers
 Overriding New and Delete
 Time and Date Manipulation
  Defining Functions with a Variable Argument List
 Optimize Abstract Operations with Function Templates




Sponsored Links


Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map
Jupiterweb networks

internet.comearthweb.comDevx.comClickZ

Search Jupiterweb:

Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents, and JupiterImages

Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers