[effective c+]レッスン後の練習を実現する小さなメモリプール

4851 ワード

effictive c++条項10は、operator newを書き換える必要がある場合は、operator deleteを同じように書き直さなければならないと考えています.ここで疑問ですが、operator newを書き換える必要があるのはいつですか?
たとえば、次のクラスが追加されます.
  
class A
{
   private:
      class B *p;
};
は、コードA*p=new A();を選択すると、システムに組み込まれたoperator new関数が呼び出され、operator new関数にはメモリが割り当てられます.このメモリにはdeleteの識別情報+Aの実際のメモリが2つ含まれています.
deleteがnewに割り当てられたメモリを合理的に削除するには、new関数がdelete関数にメモリの位置や大きさなどの情報を削除するように伝えなければならないため、これまで小さなクラスAはnewの時にいくつかのフラグ情報を複数回、メモリが緊張している場合には、複数回のnew Aを繰り返す必要があり、このフラグ情報は多くのメモリを占有していた.operator new関数の書き換えを考慮する必要があります.
具体的にはoperator new関数にチェーンテーブルとして一度に多くのメモリブロックを割り当て,newのたびに現在使用されていないものを割り当て,現在のoperator newの結果を返す.
コードは次のとおりです.
#include <iostream>

class airplanerep
{
public:
	airplanerep(){}
	~airplanerep(){}

};
class airplane
{
public:
	airplane(): rep(0)
	{ 
		rep = new airplanerep();
	}
public:
	static void* operator new(size_t size);
	static void operator delete(void* deadobject, size_t size);
private:
	union
	{
		airplanerep *rep;
		airplane *next;
	};
	static const int block_size;
	static airplane *headoffreelist;
};

airplane* airplane::headoffreelist = 0;
const int airplane::block_size = 512;

void* airplane::operator new(size_t size)
{
	if (size != sizeof(airplane))
	   return ::operator new(size);
	airplane *p = headoffreelist; // p          
	if (p)
		headoffreelist = p->next;
	else
	{
		//       ,          ,
		//     block_size airplane  
		airplane *new_block = static_cast<airplane*>(::operator new(block_size * sizeof(airplane)));
		//                  
		//   0   ,        operator new     
		for (int i = 1; i < block_size; ++i)
			new_block[i].next = &new_block[i+1];

		//        
		new_block[block_size - 1].next = 0;

		// p      ,headoffreelist         
		p = new_block;
		headoffreelist = &new_block[1];
	}
	return p;
}

void airplane::operator delete(void* deadobject, size_t size)
{
	if (0 == deadobject)
		return;
	if (size != sizeof(airplane))
	{
		return ::operator delete(deadobject);
	}
	
	airplane * carcass = static_cast<airplane*>(deadobject);
	carcass->next = headoffreelist;
	headoffreelist = carcass;

}
class A 
{
public:
	void show()const {std::cout << i << std::endl;}
private:
	int i;
};


int main()
{

	//     operator new    ,   new   ,               ,                 
	// 
	airplane *my_airplane_one = new airplane;
	delete my_airplane_one;
	
// 	A *p = new A[2];
// 	delete []p;

	return 0;
}
授業後のpollスレッドプールでコードをより明確にし、同時にテンプレートを使用します.多くは言いませんが、たぶん同じです.
コード:
#include <iostream>

class airplanerep
{
public:
	airplanerep(std::string name_val = "", size_t size_val = 0): name(name_val), size(size_val){}
	~airplanerep(){}

public:
	std::string get_name()const {return name;}
	size_t get_size()const { return size;}
private:
	std::string name;
	size_t  size;
};

template< typename obj_type>
class poll
{
public:
	poll(){}
public:
	void* alloc(size_t size);
	void free(void* p, size_t size);

private:
	union data_unit
	{
		obj_type *ref;
		data_unit *next;
	};
	data_unit * headoffreelist;
	static size_t block_size;
};

template <typename obj_type>
size_t poll<obj_type>::block_size = 20;

template <typename obj_type>
void* poll<obj_type>::alloc(size_t size)
{
	if (size != sizeof(data_unit))
		return ::operator new(size);
	data_unit *p = headoffreelist; // p          
	if (p)
		headoffreelist = p->next;
	else
	{
		//       ,          ,
		//     block_size airplane  
		data_unit *new_block = static_cast<data_unit*>(::operator new(block_size * sizeof(data_unit)));
		//                  
		//   0   ,        operator new     
		for (size_t i = 1; i < block_size; ++i)
			new_block[i].next = &new_block[i + 1];

		//        
		new_block[size - 1].next = 0;

		// p      ,headoffreelist         
		p = new_block;
		headoffreelist = &new_block[1];
	}
	return p;
}
template <typename obj_type>
void poll<obj_type>::free(void* p, size_t size)
{
	if (0 == p)
		return;
	if (size != sizeof(p))
	{
		return ::operator delete(p);
	}

	data_unit * carcass = static_cast<data_unit*>(p);
	carcass->next = headoffreelist;
	headoffreelist = carcass;
}
class airplane
{
public:
	airplane(): rep(0)
	{ 
		rep = new airplanerep("my_airplane_name", 100);
	}
public:
	static void* operator new(size_t size);
	static void operator delete(void* p, size_t size);
private:
	airplanerep * rep;
	static poll<airplane>  mem_poll;
};

poll<airplane> airplane::mem_poll;

void* airplane::operator new(size_t size)
{
	return mem_poll.alloc(size);
}



void airplane::operator delete(void* p, size_t size)
{
	mem_poll.free(static_cast<airplane*>(p), size);
}


int main()
{

	airplane* p = new airplane();
	delete p;
	return 0;
}
私が更に见る时理解することができることを望みます!!