`

c++ - placement operator new() and the operator delete()

    博客分类:
  • c++
 
阅读更多

A class member operator new() can be overloaded. Provided that each delcaration has a unique paramter list. The first parameter of any class operator new() must always be a parameter of type size_t, for example. 

 

 

 

class Screen
{
public :
   void *operator new (size_t); 
   void *operator new(size_t, Screen*);
};

 

 

and how you can use the the placement operator as follow.

 

 

 

void func(Screen * start) 
{
   Screen *p = new (Start) Screen;
   //...
}

 

 

 

NOTE: it is also possible to overload the class member  operaotr delete(). However, such an operator is never inovked from a delete expression. An overloaded operator delete() is only called implicitly by the implementation if the constructor called by a new expression (yes, this is not a typo) throw an expression.

 

given the expression, 

 

 

Screen *ps = new (Start) Screen;

 

 

are as follow.

 

 

 

  1. It calls the class operaor new (size_t, Screen *)
  2. It then calls the default constructor for class Screen to initialize the object
  3. It then initializes ps with the address of the Screen object
what if the step 2 throws an exception, we hvae to ensure the memory is not leaked, the class designer can provide a overload delete() operator in this situation. 

If the class designer provides an overload operator delete() with parameters with types that match the parameter type of operator new (), the implementation automatically calls this operator delete() to deallocate the storage, 

for example.

Screen * ps = new (Start) Screen;
 
if the default constructor for class Screen exists by throwing an exception, the implementation looks  for an operator delete() to be considered, it must have types that matches those of the new operator new() called. 

First parameter of the new operator and the first parameter of the delete operator are size_t and void * repsectivly. they are not considered for this comparision.


void operator delete(void *, Screen *)
 

 

 

If this operator is found under class Screen, it is called to deallocate the storage if the constructor called by the new expression throws an exception. If this operator delete is not found(), then no operator delete() is called. 

 

 

Let 's see the 

 

 

/**
* file 
*   Screen.h
*
*  description:
*   this is the header file definition of the screen and the ScreenPtr
*/

class Screen
{
public:
	void move(int x, int y);

	/** 
	* the placement new and delete operator
	*
	*/
	void *operator new(size_t );
	void *operator new(size_t, Screen*  );

	/** the placement delete operator 
	*
	*
	*/
	void operator delete(void *);
	void operator delete (void * , Screen *);

	Screen() { };
	Screen(Screen *) { throw "Screen(Screen *); ";}
private:
protected:
};
 

 

 

and below is the implementation code. 

 

 

/**
* file 
*   Screen.h
*
*  description:
*   this is the header file definition of the screen and the ScreenPtr
*/
#include "stdafx.h"
#include "Screen.h"
#include <iostream>
#include <exception>

using std::cout;
using std::endl;
using std::cerr;
using std::exception;

void * Screen::operator new(size_t size) { 
	cout << "void * Screen::opreator new (size_t size) " << endl;
	return ::new char[size];
}
void * Screen::operator new(size_t size, Screen* start) {
	cout << "void * Screen::operator new (size_t size, Screen* start) " << endl;
	if (start == NULL) // if you provide a placement new operator and the placement new operaor allocate memory, then you should provide a overloaded delete operator
	{
		throw new exception("bad argument - " "start");
	}
	return start;
}

void Screen::operator delete(void * ptr) 
{
	cout << "void Screen::operator delete(void* start) " << endl;
	::delete ptr;
}

void Screen::operator delete(void * ptr, Screen * start)
{
	cout << "void * Screen::operator delete (void * ptr, Screen* start) " << endl;
	// do nothing...
}
 

 

 

Below is the test code

 

 

 

/**
*  func(Screen* start) 
*/
// what is steps of the calls of Screen* ps =   new (start) Screen;
// 1. it calls the class operaor new (size_t, Screen *)
// 2. it then calls the default constructor for class Screen to initialize the object
// 3. it then initializes ps with the address of the Screen object
void func(Screen * start) 
{
	Screen* ps = new (start) Screen;
	delete ps; // it calles void Screen::operator delete(void * ptr) , not void Screen::operator delete(void * ptr, Screen start) 
}

void func2()
{
	Screen *ps = new Screen;
	delete ps; // it calls void Screen::operator delete(void * ptr) 
}


void func3(Screen * start) 
{
	try 
	{
		Screen *ps = new (start) Screen(start);
		delete ps; // this is never reached.
	}
	catch (const char *) {
		// you will probably see the "void Screen::operator delete(void * ptr, Screen * start)" called.
	}
}

void func4()
{
	try 
	{
		Screen *ps = new Screen(NULL);
		delete ps; // this line of code is never reached.
	}
	catch (const char *) 
	{
		// you will probably see the "void Screen::operator delete(void * ptr)" called.
	}
}        int _tmain(int argc, _TCHAR* argv[])
{
	//test_use_of_ptr_overload();
	Screen * screen  = new Screen();
	func(screen);
	func2();
	screen = new Screen();
	func3(screen);
	delete screen;
	func4();
	return 0;
}
 

 

and the output is like this: 

 

 

 

void * Screen::opreator new (size_t size)
void * Screen::operator new (size_t size, Screen* start)
void Screen::operator delete(void* start)
void * Screen::opreator new (size_t size)
void Screen::operator delete(void* start)
void * Screen::opreator new (size_t size)
void * Screen::operator new (size_t size, Screen* start)
void * Screen::operator delete (void * ptr, Screen* start)
void Screen::operator delete(void* start)
void * Screen::opreator new (size_t size)
void Screen::operator delete(void* start)
 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics