operator new/placement new 和 内存池 技术

1.new 操作符总结
 (1) operator new/delete函数的重载规则和行为
     operator new/delete可以在类中进行重载。但是不能在全局重载原型为:void operator new(size_t size) 的函数。
    
     operator new的行为是:首先分配内存,再调用构造函数,最后类型转换并返回指针。
     operator delete的行为是:首先调用析构函数,然后再释放内存。
    
 (2) placement new
     placement new的语法:
         ClassType *p = new (buff)ClassType;
        
     placement new 的作用是:
         在一块已经存在的内存上调用对象的构造函数,得到一个对象指针。
         需要注意的是最后需要一个显示的调用对象的析构函数的过程。
    
     ex:
         class A{};

         void test()
         {
             void * pTest = new char[sizeof A];
             A *pA = new (pTest)A;
             pA->~A();
             delete pTest;
         }

 

2.内存池技术
    (1) new在某些应用中的问题
        new (int);这个语句分配的内存由两部分组成:第一部分我们称之为cookie,用来记录分配的内存的信息,这部分信息包含内存的大小等信息,供 delete 使用; 第二部分才是应用程序需要的信息, 大小为sizeof(int)的一段内存。
       
        现在有一个程序需要构造很多个小对象,如果我们全部用 new 去构造这个小对象的话,那么就会有很多的cookie产生, 这样内存肯定就会有很大的浪费,而且每次调用new 也会让程序变慢。
       
        我们怎样解决这个问题?使用到的技术就是内存池:由预先分配内存这个概念和 placement new这个技术实现。

    (2)内存池的一般思想
        首先由内存池分配比较大的一个内存块(比如20M),然后把这个内存块细分,每个小块的大小是我们对象的大小。这些小块是通过链表管理的。当需要分配一个对象时就从链表里面取出一个小块,并把这个小块从链表里面删除掉;如果链表 的小块用完了,那么就再分配一个内存块(比如20M),并且也把这个块细分为我们对象的大小的小块加到链表里面。释放这个对象的时候,就把这个对象占用的这个小块内存放到链表里面。
        如下图:
       
        这里的好处是 cookie只在分配内存块的时候出现了一次,以后再没有出现;并且能够知道那些内存没有释放,那些释放了。

 

        在实际应用中,我们的对象可能有很多种,比如对象的大小可以是4kb、8kb、16kb等。所以我们可以在内存池中有多个链表, 每个链表的维护不同尺寸的小块。

 

3.应用举例    
    下面一个STL::alloc的实现作为例子:
    STL::alloc维护了16种list,分别用来处理8,16,24,32 ... 到 128 byte尺寸的小区块需求。对于不为8的倍数的需求,会被转为8的倍数; 对于超出了128byte的区块,会被认为cookie的浪费比例可以被忽略不计,直接调用 new/delete操作。
    STL::alloc设计比较经典的地方在于,当系统没有可用资源的时候,会从维护的list中去取。直到资源耗尽。
   
    但是STL并不释放已经分配的资源,只有才程序结束后才释放资源。

 

 

 
   

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值