C++动态内存分配(new/new[]和delete/delete[])详解分享

用了malloc( )和free( ),所以我们很可能会没有调用析构函数就释放了内存。如果正在删除的对象指针是 0,将不发生任何事情。为此,建议在删除指针后立即把指针赋值为0以免对它删除两次。对一个对象删除两次一定不是一件好事,这会引起问题。

当创建一个new表达式时有两件事发生。首先,使用运算符new分配内存,然后调用构造函数。在delete表达式里,调用析构函数,然后使用运算符 delete释放内存。我们永远无法控制构造函数和析构函数的调用(否则我们可能意外地搅乱它们),但可以改变内存分配函数运算  符new和delete。被new和delete使用的内存分配系统是为通用目的而设计的。但在特殊的情形下,它不能满足我们的需要。改变分配系统的原因是考虑效率:我们也许要创建和销毁一个特定的类的非常多的对象以至于这个运算变成了速度的瓶颈。 C++允许重载new和delete来实现我们自己的存储分配方案,所以可以像这样处理问题。   

  另外一个问题是堆碎片:分配不同大小的内存可能造成在堆上产生很多碎片,以至于很快用完内存。也就是内存可能还有,但由于是碎片,找不到足够大的内存满足我们的需要。通过为特定类创建我们自己的内存分配器,可以确保这种情况不会发生。 
在嵌入和实时系统里,程序可能必须在有限的资源情况下运行很长时间。这样的系统也可能要求分配内存花费相同的时间且不允许出现堆内存耗尽或出现很多碎片的情况。由客户定制的内存分配器是一种解决办法,否则程序设计者在这种情况下要避免使用new和delete,从而失去了C + +很有价值的优点。 

当重载运算符new和delete时,记住只改变原有的内存分配方法是很重要的。编译器将用new代替缺省的版本去分配内存,然后为那个内存调用构造函数。所以,虽然编译器遇到new 时会分配内存并调用构造函数,但当我们重载new时,可以改变的只是内存分配部分。(delete 也有相似的限制。)

当重载运算符new时,也可以替换它用完内存时的行为,所以必须在运算符new里决定做什么:返回0、写一个调用new – handler的循环、再试着分配或用一个 bad_alloc异常处理重载new和delete与重载任何其他运算符一样。但可以选择重载全局内存分配函数,或为特定的类使用特定的分配函数

    当全局版本的new和delete不能满足整个系统时,对其重载是很极端的方法。如果重载全局版本,那么缺省版本就完全不能被访问—甚至在这个重载定义里也不能调用它们。

重载的ne w 必须有一个size_t 参数。这个参数由编译器产生并传递给我们,它是要分配内存的对象的长度。必须返回一个指向等于这个长度(或大于这个长度,如果我们有这样做的原因)的对象的指针,或如果没有找到存储单元(在这种情况下,构造函数不被调用),返回一个0。然而如果找不到存储单元,不能仅仅返回0,还应该调用new-handler或进行异常处理,通知这里存在问题。

运算符new的返回值是一个void *,而不是指向任何特定类型的指针。它所做的是分配内存,而不是完成一个对象的建立—直到构造函数调用了才完成对象的创建,这是由编译器所确保的动作,不在我们的控制范围内。

运算符delete接受一个指向由运算符new分配的内存的void *。它是一个void *因为它是在调用析构函数后得到的指针。析构函数从存储单元里移去对象。运算符 delete的返回类型是void。

下面提供了一个如何重载全局new和delete的简单的例子:

  #include <stdlib.h>      void * operator new(size_t sz)   {     printf("operator new:%d bytesn",sz);     void* m=malloc(sz);     if(!m) puts("out of memory");     return 0;   }   void operator delete(void* m)   {   puts("operator delete");   free(m);   }   class s   {     int i[100];   public:     s(){puts("s::s()");}     ~s(){puts("s::~s()");}   };   int main()   {    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 an s[3]");    s* SA=new s[3];    delete [] SA;   }

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/488054.html

(0)
上一篇 2020年11月12日
下一篇 2020年11月12日

精彩推荐