C++内存分配详解三:内存分配模型

侯捷C++内存分配课程总结三:内存分配模型

文章内容参照于侯捷 C++内存分配系列教程


回顾:重载new行为的目的

在之前的文章中,我门了解到malloc在分配内存的时候会额外分配出一些不能为用户所使用的内存块。当我们多次分配内存时,这一个开销会变得越来越大。而我们重载new行为的最重要的目的就是减少调用malloc分配内存所产生的额外开销。


一、内存分配模型:内存池

我们在开始讨论这种内存分配模型之前需要先明确一个问题:我们无法改变malloc的动作(除非我们去修改源码)。这也意味着我们无法改变每次调用malloc都会产生的额外开销,所以,我们去进行优化的方法就只能时减少对malloc的调用次数

实现方法:

  1. 在第一次分配内存时,调用malloc一次性分配一大块内存,称为内存池
  2. 当需要分配内存时,首先检查内存池是否有足够的容量,如果有就直接从内存池中为其分配内存,若不存在则调用malloc为内存池再次补充一大块内存
  3. 当已经被分配出的内存释放时,将它还于内存池

如此,我们可以很简单的减少了malloc的调用次数,尽管每一次调用malloc都要产生额外开销,但相比直接调用malloc会优化了很多。这里所说的只是大体的实现,下面我们去看更多的细节。


二、具体实现

1.C++prime中的实现

代码来自于C++prime

	//对于类的定义
	class Screen {
   
	public:
		Screen(int x) :i(x) {
   };
		int get() {
    return i; }
	
		void * operator new(size_t);//重载new的行为
		void operator delete(void *, size_t);//重载delete的行为
	private:
		Screen *next;//仅用于内存池的中,指向下一块可用的内存
		static Screen * freeStore;//内存池头节点的指针
		static const int screenChunk;//每次分配的数量
	private:
		int i;
	};
	Screen *Screen::freeStore = 0;
	const int Screen::screenChunk = 24;

我们首先分析这个类的定义:

  1. 构造函数、数据成员i和方法get,这三个成员我们不必去关心
  2. 重载了operator new 和 operator delete, 很明显,我们要改变new的行为就只能通过重载这两个函数
  3. 一根指向本体的指针:这根指针的作用是,当当前成员还在内存池中时,用于连接下一块内存
  4. 一根指向内存池头节点的指针,指向所维护的内存池的第一个可用内存
  5. 一个代表每次分配的数量的int,这也就是我之前说的分配一大块内存的那个一大块的数量
	//重载的operator new()
	void *Screen::operator new(size_t size)
	{
   
		Screen *p;
		if (!freeStore) {
   
			//当链表为空时,就申请一大片内存
			size_t chunk = screenChunk * size;//计算需要分配的大小
			//分配内存并将指针转型
			freeStore = p =reinterpret_cast<Screen*>(new char[chunk])
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值