#include <iostream>
using namespace std;
// Small Object Allocator
// More Effective C++ 항목8
// Modern C++ design 4장- 작은 객체의 메모리 할당기 만들기
// 메모리 할당과 소멸시간을 줄여준다.
// 메모리를 사용하지 않으면 하드디스크에 페이지 형태로 잡아놓기 때문에
// 메모리의 낭비를 걱정 하지 않아도 된다??
 
class Point
{
        int x;
        union
        {
               int y;
               Point* next;
        };
        static Point* FreeList;
public:
        Point( int a = 0, int b = 0 ) : x(a), y(b) {}
        void* operator new( size_t sz )
        {
               if( sz != sizeof(Point) )      // Point 객체 할당이 아니라면
                       return ::operator new( sz );  // 전역new를 사용하게 한다.
               if( FreeList == 0 )           // 최초 실행되는 경우
               {
                       // 전역operator new를 사용해서500개를 사용하자.
                       FreeList = (Point*)::operator new(sizeof(Point)*500);
                       // single linked list로 연결한다.
                       for( int i = 0; i < 499; ++i )
                              FreeList[i].next = &FreeList[i+1];
               }
               // 1번째 노드를 떼어서 리턴해 준다.
               Point* temp = FreeList;
               FreeList = FreeList->next;
               return temp;
        }
        // delete 시에도 아래함수가 호출된다.
        // delete는 오버로딩이 되지 않는다.
        // 단, 멤버일때 아래 모양만 허용된다. 자기를 delete를 방지??
        void operator delete( void* p, size_t sz )
        {
               if ( p == 0 ) return;         //NULL 포인터인지를 확인해줘야 한다.
               if( sz != sizeof(Point) )
               {
                       ::operator delete(p);
                       return;
               }
               // List의 제일 앞부분에 놓는다.
                Point* temp = (Point*)p;
               temp->next = FreeList;
               FreeList = temp;
        }       
};
Point* Point::FreeList = 0;
void main()
{
        Point* p1 = new Point( 1, 1 );
        Point* p2 = new Point( 2, 2 );
        Point* p3 = new Point( 3, 3 );
        cout << p2 << endl;
        delete p2;
        Point* p4 = new Point(0, 0);
        cout << p4 << endl;    // p4 와 같은주소는 p1, p2, p3중 어느것 일까요?
        delete p1;
        delete p3;
        Point* p5 = 0;
        delete p5;                    //NULL 포인터도 delete 가능하다.
}
