内存池基础应用

内存池基础应用

本文只涉及内存池的基本应用,代码以及学习资料来源于网络,刚兴趣的网友可以搜一下。我这里只是总结一下自己的想法,做一个搬运工。
再复杂的工程也离不开基础应用的实战变化,这就像上学时的教材课后习题其实才是学生最应该掌握的。基础没打好直接上附加题,没什么意义。

内存池的基础应用 嵌入式指针的应用

内存池存在的意义

  1. 频繁的malloc会使内存碎片化,尤其是频繁的malloc小块内存,浪费的更加明显。
    • 何为内存碎片化
  2. 内存池的实现手法不同,但核心思想相同
    • 减少malloc的调用次数
    • 减少malloc的此处,提高程序运行效率
  3. 内存池的实现原理
    • 首先用malloc 申请出一大块内存,远大于实际要求。当然这一大块内存是连续的,当要分配的时候,从一大块内存中一点一点分配给你。
    • 大块内存使用完毕后,再申请一块同样大的内存,再一点一点分配给你
    • 如此往复
  4. 提高运行效率,减少内存浪费

内存池代码举例

  • 这套代码的整体思想是,创建一大片空间,空间大小为 n * sizeof(class A);
  • 后续每new出来一个class A类型的指针,都从这片连续内存池里取空间
  • 池子用完了,可以自动申请出另一片大小相同的池子
  • 池子中的位置都分配出去了,当有空位置 即有人要删除这个位子上的内容 则可以清空这个位置,这个位置在赤字中就为空,等待下一次分配
  • 这个实例的缺陷是 如果A类是实战类,那么每次都要准备一个4字节指针,形成链路
class A
{
public:
    static void * operator new(size_t size);
    static void operator delete(size_t size);
private:
    A * next;
    static A * m_FreePos;
    static int m_TrunckCount;
}

A * A::m_FreePos = nullptr;
int A::m_TrunckCount = 5;

void * A::operator new(size_t size)
{
    A * tmplink;
    if(m_FreePos == nullptr)
    {
        size_t realsize = m_TrucnkCount * size; //申请了多少个字节
        m_FreePos = reinterpret_cast<A*>(new char[relsize]);//坑位已经帮你设置好了
        tmplik = m_FreePos;

        //分配出来的一大块内存,共5小块A类,彼此互联,供后续使用
        //只处理了4个,最后一个要单独处理
        for(;tmplink != &m_FreePos[m_TrunckCount-1]; ++tmplink)
        {
            tmplink->next = tmplink+1;
        }
        //这里循环出来时 最后一个
        tmplink->next = nullptr;
    }
    tmplink = m_FreePos;
    m_FreePos = m_FreePos->next;
    return tmplink;
}

void A::operator delete(void *phead)
{
    (static_cast<A*>(phead))->next = m_FreePos;
    m_FreePos = static_cast<A*>(phead);
}

int main(int argc,char **argv)
{
    for(int i = 0;i<50000000;i++)
    {
        A *pa = new A();
    }
    return 0;
}

嵌入式指针 – 指针的嵌入式应用

嵌入式指针是指 在类A中有一个结构体,结构体中只有一个元素,是一根指针
用这跟指针去嵌入到另一个类B中,可以理解为寄生,用这跟寄生在B类对象中的指针,链接到另一个相同的类B的对象中,形成串联的.
然这些串联的对象B,一起拉到A类构造的池子中。

  • 思想: 在 A类中构造池子,把B类对象塞到池子里,池子的坑位一旦有对象了,这个坑位的内容就会被对象本身的内容塞满。坑位的obj->next 就没有指向了。
  • 核心技巧: 池子的空间肯定是连续的。那么问题来了
    • 问题一: 如何给池子划分坑位
      • 不同于上一例子中,上一例子坑位已经划分好了
      • 用obj* 划分坑位,精髓代码:
          tmplink->next = (obj*)((char*)tmplink + size);
      
    • 问题二: 如何把大象装进冰箱,如何把单体之间毫无关系的对象,塞到池子里的每一个坑位。
      • 即把池子里的空位置返回给申请者即可
    • 解决以上两个问题,就可以把内存池的基础应用理解明白
  • 池子中的每个坑位只管大小,不管内容。分配完大小就完事儿了。剩下的内容留给对象自己去赋值。
  • sizeof(B) > 4
    class A
    {
    public:
        void * allocate(size_t size)
        {
            obj * tmplink;
            if(m_FreePos == nullptr)
            {
                //池子如何划分坑位
                size_t realsize = m_TrunckCount * size;
                m_FreePos = (obj*)malloc(realsize);
                tmplink = m_FreePos;
                //指处理4个坑位
                for( int i = 0;i < m_TrunckCount -1; ++i)
                {
                    tmplink->next = (obj*)((char*)tmplink + size);
                    tmplink = tmplink->next;
                }
                //最后一个坑位
                tmplink->next = nullptr;
            }

            //把大象装进冰箱里
            tmplink = m_FreePos;
            m_FreePos = m_FreePos->next;
            return tmplink;
        }

        void deallocate(void *phead)
        {
            ((obj*)phead)->next = m_FreePos;
            m_FreePosi = (obj*)phead;
        }
    private:
        struct obj 
        {
            struct obj * next;
        }
        int m_TrucnkCount = 5;
        obj * m_FreePos = nullptr;
    }

    class B //类的大小要大于 4
    {
    private:
        static A myalloc;
        static void * operator new(size_t size)
        {
            return myalloc.allocate(size);
        }
        static void operator delete(void *phead)
        {
            return myalloc.deallocate(phead);
        }

    public:
        int m_i;
        int m_j;
    }

    int main(int argc,char **argv)
    {
        A * pa[100];
        for(int i = 0; i < 15; i++)
        {
            pa[i] = new A();
            pa[i]->m_i = 12;
            pa[i]->m_j = 15;
        }
        return 0;
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值