[effective c++]实现课后练习的一个小的内存池

  effictive c++条款10认为如果有必要重写operator new,就必须同样的要重写operator delete,这里有个疑问,该什么时候需要重写operator new 呢?

  举例说明,加入有如下的类:

  

class A
{
   private:
      class B *p;
};
在代码 A *p = new A(); 时,会调用系统内置的operator new 函数,operator new函数会分配一段内存,这个内存包括2部分: 方便delete的标识信息 + A实际内存。

因为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;
}
希望我再看的时候能过看懂!!

转载于:https://my.oschina.net/cghy2011/blog/106077

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值