C++封装使用隐式链表维护固定长度的内存池

所谓固定长度内存池是指每次从内存池申请的内存长度是不能变的,如果内存池初始化每块内存的大小是100字节,那么每次申请出来的内存长度就是100字节,不会多也不会少。

固定长度的内存池有很多的应用场景,比如图像的编解码,码率的固定导致每帧图像的大小是比较固定的,因此可以使用固定长度的内存池来优化图像缓存的申请和释放。


隐式链表是一个单向的链表,使用每块空闲内存块的前四个字节来保存下一块空闲内存块的地址


完整代码如下:

class CFixSizeMemPool
{
public:

    //构造函数申请内存
    CFixSizeMemPool(unsigned int iBlockSize, unsigned int iBlockCount)
    {
        //由于需要用块内存构造空闲链表,因此块长度必须大于一个地址的长度
        if (iBlockSize < sizeof(void*))
        {
            iBlockSize = sizeof(void*);
        }
        m_iBlockSize = iBlockSize;
        m_iBlockCount = iBlockCount;

        //向操作系统申请整块内存
        m_pcMemPool = (char*)::malloc(iBlockSize * iBlockCount);
        if (m_pcMemPool == 0)
        {
            throw std::exception("no memory.");
        }

        //初始化空闲块链表
        buildFreeLink();
    }

    //析构函数释放整块内存
    ~CFixSizeMemPool()
    {
        ::free(m_pcMemPool);
        m_pcMemPool = 0;
    }

    //申请一块内存
    void* malloc(unsigned int iLen)
    {
        //申请的内存长度不能大于块的长度
        if ((iLen > m_iBlockSize) || (m_pcFreeBlock == 0))
        {
            return 0;
        }

        //分配出空闲块链表头上内存块,同时链表头指向下一空闲块
        char *pcBlock = m_pcFreeBlock;
        m_pcFreeBlock = *((char **)pcBlock);
        return pcBlock;
    }

    //释放一块内存
    void free(void *pMem)
    {
        //判断内存地址是否有效
        if ((pMem < m_pcMemPool) ||
            (pMem > (m_pcMemPool + (m_iBlockSize * m_iBlockCount))))
        {
            return;
        }

        //判断内存是否和块大小是对齐的
        if (((char*)pMem - m_pcMemPool) % m_iBlockSize != 0)
        {
            throw std::exception("invalid address.");
        }

        //把内存块放到空闲链表头上
        *((char **)pMem) = m_pcFreeBlock;
        m_pcFreeBlock = (char*)pMem;
    }

private:

    //初始化空闲内存块队列
    void buildFreeLink()
    {
        char **pcNextFreePtr = 0;
        for (unsigned int i=0; i<m_iBlockCount; ++i)
        {
            pcNextFreePtr = (char**)(m_pcMemPool + (i * m_iBlockSize));
            *pcNextFreePtr = m_pcMemPool + (i+1) * m_iBlockSize;
        }
        *pcNextFreePtr = 0;
        m_pcFreeBlock = m_pcMemPool;
    }

    unsigned int m_iBlockSize;     //每块的大小
    unsigned int m_iBlockCount;    //块的数量
    char *m_pcFreeBlock;  //指向空闲块链表的头
    char *m_pcMemPool;    //指向整块内存的地址
};






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值