I'm not sure if this is completely accurate, but it should be pretty close...
Code:
#include <cstdlib>
#include <iostream>
using namespace std;
/*
wrappers for invoking constructors and
destructors 'in place' on raw memory
*/
template < typename Type >
inline
Type &
constructor( Type & object )
{
return *new( &object ) Type( );
}
template < typename Type >
inline
Type &
constructor( Type & object, Type const & value )
{
return *new( &object ) Type( value );
}
template < typename Type >
inline
Type *
constructor( Type * array, size_t size )
{
return new( array ) Type[ size ];
}
template < typename Type >
inline
void
destructor( Type & object )
{
object.~Type( );
}
template < typename Type >
inline
void
destructor( Type * array, size_t size )
{
for( size_t index = 0; index < size; index++ )
destructor( array[ index ] );
}
/*
overriding class-specific new/delete
note: these *must* not throw exceptions
*/
struct special
{
special( void )
{
cout << "special::special( ) at address " << ( int * )this << endl;
}
static
void *
allocate( size_t size )
{
void * address = malloc( size );
cout << "special::allocate " << size << " bytes at address " << ( int * )address << endl;
return address;
}
static
void *
operator new( size_t size )
{
return allocate( size );
}
static
void *
operator new[ ]( size_t size )
{
return allocate( size );
}
/*
new/new[] for 'in place' construction. note: the second parameter
can be overloaded for special types (such as pool allocators)
*/
static
void *
operator new( size_t size, special * address )
{
cout << "(in place) special::operator new[ ] at address " << ( int * )address << endl;
return address;
}
static
void *
operator new[ ]( size_t size, special * address )
{
/*
the compiler seems to think we need extra bytes
for book keeping, as if we were allocating memory
(why??). is this a portable approach?
*/
size_t const array_book_keeping_bytes = 4;
cout << "(in place) special::operator new[ ] at address " << ( int * )address << endl;
return ( char * )address - array_book_keeping_bytes;
}
static
void
deallocate( void * address )
{
cout << "special::deallocate at address " << ( int * )address << endl;
free( address );
}
static
void
operator delete( void * address )
{
deallocate( address );
}
static
void
operator delete[ ]( void * address )
{
deallocate( address );
}
~special( void )
{
cout << "special::~special( ) at address " << ( int * )this << endl;
}
char buffer[ 1024 ];
};
struct standard
{
standard( void )
{
cout << "standard::standard( ) at address " << ( int * )this << endl;
}
~standard( void )
{
cout << "standard::~standard( ) at address " << ( int * )this << endl;
}
char buffer[ 1024 ];
};
/*
overriding global new/delete
*/
void *
allocate( size_t size ) throw( std::bad_alloc )
{
void * address = malloc( size );
if( address == 0 )
throw std::bad_alloc( );
cout << "global allocate " << size << " bytes at address " << ( int * )address << endl;
return address;
}
void *
operator new( size_t size ) throw( std::bad_alloc )
{
return allocate( size );
}
void *
operator new[ ]( size_t size ) throw( std::bad_alloc )
{
return allocate( size );
}
template < typename Type >
void *
operator new( size_t size, Type * address )
{
cout << "(in place) global operator new[ ] at address " << ( int * )address << endl;
return address;
}
template < typename Type >
void *
operator new[ ]( size_t size, Type * address )
{
size_t const array_book_keeping_bytes = 4;
cout << "(in place) global operator new[ ] at address " << ( int * )address << endl;
return ( char * )address - array_book_keeping_bytes;
}
void
deallocate( void * address )
{
cout << "global deallocate at address " << ( int * )address << endl;
free( address );
}
void
operator delete( void * address )
{
deallocate( address );
}
void
operator delete[ ]( void * address )
{
deallocate( address );
}
int
main( void )
{
size_t const elements = 4;
/*
use class-specific memory management
*/
delete [ ] new special[ elements ];
/*
use 'in place' constructor/destructor
*/
char special_buffer[ sizeof( special ) * elements ];
constructor( ( special * )special_buffer, elements );
destructor( ( special * )special_buffer, elements );
/*
use global memory management
*/
delete [ ] new standard[ elements ];
/*
use 'in place' constructor/destructor
*/
char standard_buffer[ sizeof( standard ) * elements ];
constructor( ( standard * )standard_buffer, elements );
destructor( ( standard * )standard_buffer, elements );
}