简单linux C++内存池

http://my.csdn.net/cyebo/code/detail/37135
在学习内存池的过程中可谓云游太虚。一般都是针对标准内存池再次实现。大部分以链表的形式讨论。诚然最正宗也最准确,但是相对比较晦涩,本文是针对刚刚接触内存池的同学写的。大大减少了对内存池整体认识的难度。
 
内存池:
如果程序中涉及频繁申请释放内存,并且每次使用的内存并不是很大,这时候应该考虑内存池。
内存池可以有有效的避免内存碎片的产生。
内存池的框架:
class MemPool{
public :
MemPool(){初始化分配N个小的内存块}
~MemPool(){真正删除整个分配了的内存空间}
void * getmem(){获取内存(块)}
void freemem(){释放内存到内存池中,这里并不是真正的释放掉内存,只是回收再利用;}
private :
struct LinkBlock * p; //把很多小内存块关联起来的结构,大部分写成链表的形式
mem_block* m_block; //一个小的内存块。
};
工作机制:
事先分配出一大块内存,再把这一大块分成很多小块。当程序中需要申请内存时就拿出一小块来用。用完了就把这一小块放回大块中(注意:这个小块内存并没释放掉!),只要不是一下用掉了所有一大块内存,无论多少次申请内存都是重复利用这些小的内存块。知道程序结束真正释放掉整片内存。
所以用内存池可以把大量的内存申请控制在可计算的范围内。内存碎片少。比如:如果用系统的 new 或者 malloc 申请10000次内存,可能要10000的小的内存空间,但是使用内存池只需申请100块空间,循环利用100次而已。作用显而易见!
 
为了让程序简单明了使用STL标准库的vector来充当小内存块的管理器。
vector< char *> vec; 这样每次申请的是vec的一个迭代器的空间。
 
代码非原创,稍稍做了改动而已。
========================================================================
MemPool.h
 
#ifndef _MEM_POOL_H  
#define _MEM_POOL_H   
#include <vector>  
#include <iostream>  
using namespace std; 
 
/*
     在内存池中分配固定大小的内存块 
     目的是加速内存分配速度,并且减少因重复分配相同 
*/ 
 
class CMemPool 
public
     
     //创建大小为blockSize的内存块,内存池数目为预分配的数目preAlloc  
     CMemPool( int blockSize, int preAlloc = 0, int maxAlloc = 0); 
     
     ~CMemPool(); 
     
     //获取一个内存块。如果内存池中没有足够的内存块,则会自动分配新的内存块  
     //如果分配的内存块数目达到了最大值,则会返回一个异常  
     void * Get(); 
     
     //释放当前内存块,将其插入内存池  
     void Release( void * ptr); 
     
     //返回内存块大小  
     int BlockSize() const
     
     //返回内存池中内存块数目  
     int Allocated() const
     
     //返回内存池中可用的内存块数目  
     int Available() const
     
private
     CMemPool(); 
     CMemPool( const CMemPool&); 
     CMemPool& operator = ( const CMemPool&); 
     
     enum 
    
         BLOCK_RESERVE = 128 
     }; 
     
     typedef std::vector< char *> BlockVec; 
     
     int m_blockSize; 
     int         m_maxAlloc; 
     int         m_allocated; 
     BlockVec    m_blocks; 
}; 
 
inline int CMemPool::BlockSize() const 
     return m_blockSize; 
 
inline int CMemPool::Allocated() const 
     return m_allocated; 
 
inline int CMemPool::Available() const 
     return ( int ) m_blocks.size(); 
#endif 
 
=========================================================
MemPool.cpp
 
 
#include "MemPool.h"  
CMemPool::CMemPool( int blockSize, int preAlloc, int maxAlloc): 
m_blockSize(blockSize), 
m_maxAlloc(maxAlloc), 
m_allocated(preAlloc) 
     if ( preAlloc < 0 || maxAlloc == 0 || maxAlloc < preAlloc ) 
    
         cout<< "CMemPool::CMemPool parameter error." <<endl; 
    
     
     int r = BLOCK_RESERVE; 
     if (preAlloc > r) 
         r = preAlloc; 
     if (maxAlloc > 0 && maxAlloc < r) 
         r = maxAlloc; 
     m_blocks.reserve(r); 
     for ( int i = 0; i < preAlloc; ++i) 
    
         m_blocks.push_back( new char [m_blockSize]); 
    
}    
CMemPool::~CMemPool() 
     for (BlockVec::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it) 
    
         delete [] *it; 
    
 
void * CMemPool::Get() 
{   
     
     if (m_blocks.empty()) 
    
         if (m_maxAlloc == 0 || m_allocated < m_maxAlloc) 
        
             ++m_allocated; 
             return new char [m_blockSize]; 
        
         else 
        
             cout<< "CMemPool::get CMemPool exhausted." <<endl; 
             return ( void *)NULL; 
        
    
     else 
    
         char * ptr = m_blocks.back(); 
         m_blocks.pop_back(); 
         return ptr; 
    
 
 
void CMemPool::Release( void * ptr) 
{  
     memset (ptr,0, sizeof ( char )*m_blockSize); //内存回收回来以后并没销毁,原数据仍在,所以应该清空
     m_blocks.push_back( reinterpret_cast < char *>(ptr)); 
}  
 
=========
main.h
 
#include "stdafx.h"
#include "MemPool.h"
#include <string.h>
int main( int argc, char * argv[])
{
CMemPool *m_cache = new CMemPool(50,0,10);
 
char * src_date= "abcdefg" ;
char *p1=( char *)(m_cache->Get());
char *p2=( char *)(m_cache->Get());
int *p3=( int *)(m_cache->Get());
strcpy (p1,src_date);
strcpy (p2,src_date);
p3[0]=9;p3[1]=25;
 
m_cache->Release(p1);
m_cache->Release(p2);
m_cache->Release(p3);
 
//把MemPool.cpp中void CMemPool::Release(void* ptr) 的
//memset(ptr,0,sizeof(char)*m_blockSize);注释掉可以验证每次内存回收以后是重复利用而非销毁
cout<<*( int *)(m_cache->Get())<<endl;
cout<<( char *)(m_cache->Get())<<endl;
cout<<( char *)(m_cache->Get())<<endl;
delete m_cache;
     return 0;
}
 
完毕!
 
当然这只是探究内存池而已,更高级的比如线程安全,内存扩容,模板等等,仍需解决。
但是相信想初窥内存池门径应该还是有帮助的!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值