Overloading placement new and placement delete operators


Overloaded placement new and placement delete have the same form with their corresponding new and delete operator.The only difference is that placement new and delete must accept more than one arguments.The type of the first argument accepted by the placement new and placement delete must be same as the new and delete operator-size_t type for new operator and void* for delete operator,while the second argument for both the operators-placement new and placement delete must be void* type,the remaining arguments can be of any type.Here is a simple way to overload the placement new and placement delete.

Link : Overloading new and delete operator

void* operator new(size_t sz , void* vd) ///placement new function
{
return vd ;
}

void operator delete(void *vMem , void* vd) ///placement delete function
{
::operator delete(vMem , vd) ;
}

Placement delete is analogous to delete operator but we do not require calling placement delete whenever placement new is used.This is sometimes due to the fact that placement new uses the storage in stack to construct the new object,but even if the storage passed was allocated in heap placement delete is still not called when delete operator is call to deallocate the storage.Consider the program below where we will pass a dynamic storage to placement new,the delete operator must be called to delete the storage.

class Real
{
private:
 int i;
 
public:
 Real(int ii=0):i(ii) { cout<<“Constructor \n”; }
 
 void* operator new(size_t sz,void *vd, int arg3) ///placement new
 cout<<“Placement new \n” ;
 cout<< arg3 ;
 return vd;
 }
 
 void* operator new(void* MemSt , void *vd) {///Placement delete
 cout<<“Placement delete overloaded function \n”;
  ::operator delete(Mem,vd);
 }
 
 void* operator delete(void* vd) { ///operator delete
 cout<<“Delete overloaded function \n”;
 ::operator delete vd;
 }

 ~Real( ) { cout<< “Destructor \n” ; }
} ;
 
int main( )
{
Real *rl=new(new int()) Test(100) ;

delete rl ;

cin.get( ) ;
return 0 ;
}

The program runs perfectly fine and you will notice when delete is called on ‘rl’ placement delete is not called instead the normal delete operator is called.In fact placement delete is never call in the program shown above or any other program that you might come across.It seems the compiler reserve the placement delete call only for some rare minimum case,but what is that rare case? you will find the answer below.






When is placement delete call or use of placement delete operator

Before we discuss the case which initiate the call of placement delete operator we will have to understand the process involve while calling the new or placement new operator.

There are two steps that occur every time a new operator is called(but just one step for placement new operator call):
 
Step 1:The new operator will allocate the memory according to the given size.For placement new allocation of memory does not occur.

Step 2:After the allocation the constructor of the object for which the allocation is made will be called to initialize the memory.After this the address of the memory is return to the place where new operator was called and this address is assigned to the pointer(whichever is on the left side of the new or placement new operator).This step definitely occur in placement new call also.

Suppose while using placement new in the second step after constructor has been called,if the constructor pass an exception then the remaining process never occur.That means the pointer on the calling side is never assigned the address of the memory.Ultimately we cannot used delete operator on the pointer to delete the storage.Now the storage is left freely with no accessible pointer pointing to it.In such scenario the compiler will try to delete the storage but it cannot call the normal delete operator since placement new was used so it calls the placement delete operator instead to delete the storage during run-time.This ensure there is no memory leakage in our program.But off course for this to be possible you must include the overloaded placement delete operator else the compiler cannot call the placement delete function.You cannot expect the compiler to generate a placement delete function out of nowhere and call it.Hence,it must be included for the call.

The program given below shows an instance of the condition discussed.

class test_placement_del
{
 int i ;

public:
 test_placement_del( int ii=0 ):i(ii)
{
 cout<<“Constructor \n” ;
 throw bad_alloc() ; ///throwing exception
}

void operator delete( void *n ) throw() ///delete operator overloaded
{
 cout<<“Delete operator function \n” ;
 ::operator delete(n) ;
}

/***Placement new overloaded version ***/
void * operator new(size_t sz , void *vd) throw( )
{
 cout<<“New placement called \n”;
 return vd ;
}
///Overloading placement delete
void operator delete(void* MemSt , void *vd) throw()
{
 cout<<“Delete placement called \n” ;
 ::operator delete(MemSt , vd) ;
}

~test_placement_del( ) { }
};

int main( )
{
 try {
 test_placement_del *nm=new( new int() ) test_placement_del( 9 ) ; ///passing dynamic storage to placement new
 delete nm ;

}
 catch(bad_alloc)
{
 cerr<< “Exception thrown \n” ;
}

 cin.get();
 return 0;
}

The output in Code::block,

New placement called
Constructor
Delete placement called
Exception thrown

If the program break at the line “throw bad_alloc() ;” (code::block will show a yellow arrow),then go to “settings->debugger->Default” and uncheck the box which says “Catch C++ exceptions” and run the program again.

Placement delete is called only in such rare case,but you must not discriminate the power of placement delete operator.You just can’t say that your constructor would never throw an exception and ignore to define the placement delete operator function.Mind you taking precaution is better.And in fact we must cultivate the habit of writing placement delete if placement new is ever used.


Related Link

->Dynamically allocating memory in C++ with new and delete operators.
 
->How to use placement new and placement delete operators in C++.