C++编程思想--动态创建对象(2)

来源:互联网 发布:淘宝卖衣服从哪里进货 编辑:程序博客网 时间:2024/06/12 20:05

动态创建对象(2)

  5)重载new delete,首先为什么需要重载newdelete呢?

① 也许要创建和销毁一个类的非常多的对象,以至于这个影响到了速度。

② 分配不同大小的内存可能会产生碎片,内存很快就被分配完

所以重载的时候我们只是改变了原来的分配方法,当重载时可以替换原来内存消耗完之后的行为。所以在operator new 中要决定是返回0,还是调用new-hander的循环。或者产生异常的消息。我们可以选择重载全局内存分配函数或者是针对于某个类。

(1)这是重载全局的new以及delete之后的程序以及运行结果:

#include <cstdio>#include <cstdlib>#include <iostream>using namespace std;void * operator new(size_t sz)//1.size_t 的类型是?标准C库中定义的,应为unsigned int,它是一种“整型”类型,{                             //里面保存的是一个整数,就像int, long那样。//printf("operator new :%d Bytes\n",sz);//2.这里使用的是printf,而不是cout,因为它是一个iostream对象,会调用new去分配内存,于是产生死锁cout<<"operator new "<<sz<<endl;void *m=malloc(sz);//3.申请空间返回的是void* 类型,所以它所做的只是分配内存,而非完成一个对象的创建。对象的创建要等到编译器调用构造函数才完成if (!m){puts("out of memeory");}return m;}void operator delete(void *m)//参数是void* 这是调用析构函数后得到的指针,也就是说析构函数会从构造函数中获得内存的指针{                            //返回类型为void     puts("operator delete"); free(m);}class S{int i[100];public:S(){puts("S::S()");//}//void operator delete[](void *m)//这种方式可以删除对象数组//{//puts("operator array delete");//::delete []m;//}~S(){puts("S::~S()");}};int GlobalOperatorNewTest(){puts("creating & destorying an int");int *p=new int(47);delete p;puts("creating &destorying an S");S *s=new S;delete s;puts("creating &destorying S[3]");S *sa=new S[3];//4.这里会多出空间,用于存放数组的信息,也就是说对象的数量的信息。delete []sa;return 0;}

结果:


从结果中我们可以看到首先会调用new然后再调用的是构造函数。调用了析构函数之后才会调用deleted函数。但是我们看到在释放对象数组的时候并没有调用我们自己定义的deleted函数。而是调用的系统的delete[],

那么如果在类中对数组进行delete的重载如下:

void operator delete[](void *m)//这种方式可以删除对象数组{puts("operator array delete");::delete []m;}

这是进行重载数组的delete函数之后的执行结果

(1)也可以在类中进行new的重载,只是针对这个类。

代码:

//operator new local#include <cstddef>#include <fstream>#include <iostream>#include <new>using namespace std;ofstream out("Framis01.txt");class Framis{enum{sz=10};char c[sz];static unsigned char pool[];static bool alloc_map[];public:enum{prize=100};Framis(){out<<"Framis()\n";}~Framis(){out<<"~Framis()...";}#pragma   warning(   disable   :   4290   )   void *operator new (size_t) throw(bad_alloc);void operator delete(void *);};unsigned char Framis::pool[prize*sizeof(Framis)];bool Framis::alloc_map[prize]={false};void * Framis::operator new(size_t )throw(bad_alloc)//参数后面带throw告诉编译器可以产生一个bad_alloc的异常消息。且若没有内存可以使用,也会由{                                                    //bad_alloc产生一个异常消息。  //使用类的这种创建方法,可以减少内存碎片。那么释放掉的内存可以重新使用for (int i=0;i<prize;i++){if(!alloc_map[i])//判断这块内存有没有被使用,{out<<"using block"<<i<<"...";alloc_map[i]=true;//没有使用的话,将其置为truereturn pool+(i*sizeof(Framis));//返回地址}}cout<<"out of memeory"<<endl;throw bad_alloc();}void Framis::operator delete(void *m){if(!m)//确保是地址在堆内是在正确的地址范围之内,因为很可能我们删除的是数组,然而忘记加上[]。return;unsigned long block=(unsigned long)m-(unsigned long)pool;block/=sizeof(Framis);out<<"freeing block  "<<block<<endl;//释放对应的地址空间.alloc_map[block]=false;}int main(){Framis *f[Framis::prize];try{for (int i=0;i<Framis::prize;i++){f[i]=new Framis ;}new Framis;}catch(bad_alloc)//在这里接收内存申请失败的信息。{cerr<<"Out of memory!"<<endl;}delete f[10];//这是调用全局版本的delete.f[10]=0;//删除对应的空间内容,并且使这个指针的值为0.Framis *x=new Framis;//当重新创建一个对象,对象的内容将会被放在f[10]所指的内存中,这样就充分的利用资源delete x;for (int j=0;j<Framis::prize;j++){delete f[j];}}

运行结果:

可以看到释放的内存重新被利用起来。下面是txt中的一部分内容

using block99...Framis()

~Framis()...freeing block  10

using block10...Framis()

~Framis()...freeing block  10

(1)定位new.也就是确定在哪个位置上进行分配内存,也就是可以向New函数中传递参数,但是对于delete是不能传递的,它是与new对应的。

小结:

1、C中的malloc虽然可以使用但是不安全,

2、如果对内存要求很高的时候我们不妨使用自己定义的new来申请内存空间



原创粉丝点击