`
kmplayer
  • 浏览: 508839 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

条款10:如果你写了一个opertor new,请对应写一个operator delete

 
阅读更多
1,什么时候需要撰写一份自己的new或delete?
多半是为了提高效率,例如对于需要动态配置大量细小空间的程序.
如:
class AirplaneRep{};
class Airplane
{
private:
    AirplaneRep* rep;
};


2,当我们用new配置一个Airplane对象时,实际获得的内存要比一个指针的空间多.
其原因是为了operator new和opertor delete的沟通.
缺省版的operator new可以配置任意大小的内存,同理,缺省版的operator delete应该能够释放由new配置的任意大小的内存.
因此必须通过某种办法让operator delete知道new配置了多少内存.
常用的方法:在new传回的前端"加挂"一些额外数据,说明配置的区块大小.
Airplane* pa=new Airplane;
实际获得的内存如下图所示:



3,我们可以利用每个Airplane对象的大小相同这个事实,为Airplane撰写一个定制的operator new,这样就不在需要对每个动态配置的对象分配记录区域.
常用的方法:
先用默认的new配置一大块内存,然后每一个Airplane所需的内存,便从这个大内存里挖取.
这里不要忘记还要给出定制的operator delete
实例代码:
#include <iostream>
using namespace std ;

class AirplaneRep{};
class Airplane
{
public:
    static void* operator new(size_t size);
    static void operator delete(void* collectObject,size_t size);
private:
    union
    {
        AirplaneRep* rep;
        Airplane* next;
    };
    static const int BLOCK_SIZE;
    static Airplane* headOfFreeList;
};

void* Airplane::operator new(size_t size)
{
    if(size!=sizeof(Airplane))
        return ::operator new(size);
    Airplane* p=headOfFreeList;
    //如果有效,还有内存可以分配
    if(p)
        headOfFreeList=p->next;
    else
    {
        Airplane* newBlock=static_cast<Airplane*>(::operator new(BLOCK_SIZE*sizeof(Airplane)));
        for(int i=0;i<BLOCK_SIZE-1;i++)
            newBlock[i].next=&newBlock[i+1];
        //NULL作为大内存的结束
        newBlock[BLOCK_SIZE-1].next=0;
        p=newBlock; //第一个传回
        headOfFreeList=&newBlock[1];
    }
    return p;
}

void Airplane::operator delete(void* collectObject,size_t size)
{
    if(size==0)
        return; //不执行任何操作
    if(size!=sizeof(Airplane))
    {
        ::operator delete(collectObject);
        return;
    }
    Airplane* collect=static_cast<Airplane*>(collectObject);
    //将回收的区间放在head的前端
    collect->next=headOfFreeList;
    headOfFreeList=collect;

}

Airplane* Airplane::headOfFreeList;//默认为0
const int Airplane::BLOCK_SIZE=512;

class Airplane2
{
private:
    union
    {
        AirplaneRep* rep;
        Airplane* next;
    };
    static const int BLOCK_SIZE;
    static Airplane* headOfFreeList;
};

int main ()
{
    const int cnt=128;
    //对象Airplane定制new
    Airplane* pa[cnt];
    for(int i=0;i<cnt;i++)
        pa[i]=new Airplane();
    cout<<(int)pa[127]-(int)pa[125]<<endl;
    for(int i=0;i<cnt;i++)
        delete pa[i];

    //对象Airplane2系统默认new
    Airplane2* pb[cnt];
    for(int i=0;i<cnt;i++)
        pb[i]=new Airplane2();
    cout<<(int)pb[127]-(int)pb[125]<<endl;
    for(int i=0;i<cnt;i++)
        delete pb[i];

	return 0 ;
}

4,上面new一开始分配了大量的内存,但是delete始终没有释放这块内存.
实际上,这里没有memory leak的问题.
内存泄露的问题是"配置内存后,所有指向该内存的指针都遗失了",这样内存就没有办法归还给内存.
我们的方法每一个大内存被 打破为一个个小内存,然后放置于free list中,执行new从free list中拿走,调用delete时,又会被放回free list中.
可见这些内存总是可以访问到,因此没有内存泄露的问题.
我们可以称这块大的内存为memory pool.
memory leak可能无限扩大,而memory pool的成长绝不会大过申请的内存.
由于一些病理上的行为,我们无需释放这个大的memory pool.
例如:
int main ()
{

    //获得大内存
    Airplane* pa=new Airplane();
    //释放大内存
    delete pa;

    //再次获得大内存
    pa=new Airplane();
    //再次释放
    delete pa;

	return 0 ;
}
  • 大小: 3.8 KB
分享到:
评论

相关推荐

    Redis-Operator:Redis Operator在Kubernetes上创建配置管理Redis集群

    这是一个正在进行的项目。 该项目的目的是简化环境中的部署和操作。 它于2016年在Amadeus内部开始,我们最初将该项目设计为在上运行。 这是我们的Redis-Operator的第二个版本,该版本现在基于Kubernetes ...

    redis-operator:Redis Operator通过Kubernetes上的哨兵自动故障转移创建配置管理高可用性Redis

    使用部署要创建运算符,可以直接使用kubectl创建它: kubectl create -f https://raw.githubusercontent.com/spotahome/redis-operator/master/example/operator/all-redis-operator-resources.yaml这将创建一个名为...

    2008年计算机二级考试c语言试题

    编写一个程序,接收一个2×3的二维数组,找出并输出数组中的最大值及其位置,然后输出整个数组。 #### 代码分析 ```c #include main() {int col,row,i,j; inta[2][3]; printf("Enterarray(2*3):"); for(i=0;i;i++) ...

    病人资料管理系统

    (10)在关系模式中inotice中inoticeID为主键,所以在所包含属性inoticeID的函数依赖是一个superkey。所以一定属于BCNF。 二、数据库的概念结构设计 病人资料管理系统的E-R模型 三、数据库的物理结构设计 ...

    operatorfabric-core:主操作员面料程序

    简介OperatorFabric是一个模块化,可扩展的工业强度平台,可用于电力,水和其他公用事业运营。 它旨在通过两种方式促进公用事业的运营活动: 将实时业务事件集中在一个地方,以避免使用多个屏幕/软件。 为此,...

Global site tag (gtag.js) - Google Analytics