• C++:delete和delete[]释放内存的区别


    C++中free()与delete的区别

    1、new/delete是C++的操作符,而malloc/free是C中的函数。

    2、new做两件事,一是分配内存,二是调用类的构造函数;同样,delete会调用类的析构函数和释放内存。而malloc和free只是分配和释放内存。

    3、new建立的是一个对象,而malloc分配的是一块内存;new建立的对象可以用成员函数访问,不要直接访问它的地址空间;malloc分配的是一块内存区域,用指针访问,可以在里面移动指针;new出来的指针是带有类型信息的,而malloc返回的是void指针。

    4、new/delete是保留字,不需要头文件支持;malloc/free需要头文件库函数支持。

    我们看一看malloc/free和new/delete如何实现对象的动态内存管理,见示例。

     1 class Obj
     2 {
     3 public:
     4     Obj() { cout << "Initialization" << endl; }
     5     ~Obj() { cout << "Destroy" << endl; }
     6     void Initialize() { cout << "Initialization" << endl; }
     7     void Destroy() { cout << "Destroy" << endl; }
     8 };
     9  
    10 void UseMallocFree()
    11 {
    12     Obj *a = (Obj*)malloc(sizeof(obj));
    13     a->Intialize();
    14     // ...
    15     a->Destroy();
    16     free(a);
    17 }
    18  
    19 void UseNewDelete()
    20 {
    21     Obj *a = new Obj;
    22     //...
    23     delete a;
    24 }

    类Obj的函数Initialize模拟了构造函数的功能,函数Destroy模拟了析构函数的功能。函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数Initialize和Destroy来完成初始化与清除工作。函数UseNewDelete则简单得多。

    这只是个例子,不会有人用malloc/free来创建类对象。另外,new和delete配套使用,new[]和delete[]配套使用。

    /*********************************************************

    C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]。  关于 new[] 和 delete[],其中又分为两种情况:(1) 为基本数据类型分配和回收空间;(2) 为自定义类型分配和回收空间。

    请看下面的程序。

    复制代码 代码如下:

    #include ;

    using namespace std;

    clas T {

    public:

      T() { cout << "constructor" << endl; }

      ~T() { cout << "destructor" << endl; }

    };

    int main()

    {

      const int NUM = 3;

      T* p1 = new T[NUM];

      cout << hex << p1 << endl;

      //  delete[] p1;

      delete p1;

      T* p2 = new T[NUM];

      cout << p2 << endl;

      delete[] p2;

    }

    大家可以自己运行这个程序,看一看 delete p1 和 delete[] p1 的不同结果,我就不在这里贴运行结果了。

        从运行结果中我们可以看出,delete p1 在回收空间的过程中,只有 p1[0] 这个对象调用了析构函数,其它对象如 p1[1]、p1[2] 等都没有调用自身的析构函数,这就是问题的症结所在。如果用 delete[],则在回收空间之前所有对象都会首先调用自己的析构函数。      基本类型的对象没有析构函数,所以回收基本类型组成的数组空间用 delete 和 delete[] 都是应该可以的;但是对于类对象数组,只能用 delete[]。对于 new 的单个对象,只能用 delete 不能用 delete[] 回收空间。      所以一个简单的使用原则就是:new 和 delete、new[] 和 delete[] 对应使用。

      我的理解,当用delete来释放用new int[]申请的内存空间时,由于其为基本数据类型没有析构函数,所以使用delete与delete []相同,两者都会释放申请的内存空间,若是自定义的数据类型,有析构函数时,用new []申请的空间,必须要用delete []来释放,因为要delete []时会逐一调用对象数组的析构函数,然后释放空间,如果用delete,则只会调用第一个对象的析构函数,后面对象的析构函数没有被调用,那么其空间是否释放了呢??

    delete 释放new分配的单个对象指针指向的内存

    delete[] 释放new分配的对象数组指针指向的内存

    那么,按照教科书的理解,我们看下下面的代码:

    int *a = new int[10];

    delete a;        //方式1

    delete [] a;     //方式2

    肯定会有很多人说方式1肯定存在内存泄漏,是这样吗?

    1. 针对简单类型 使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可 如:

       int *a = new int[10];

       delete a;

       delete [] a;

       此种情况中的释放效果相同 原因在于分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数,

       它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间(在分配过程中 系统会记录分配内存的大小等信息,此信息保存在结构体_CrtMemBlockHeader中,

       具体情况可参看VC安装目录下CRT\SRC\DBGDEL.cpp)

    2. 针对类Class,两种方式体现出具体差异 

       当你通过下列方式分配一个类对象数组:

       class A

       {

       private:

          char *m_cBuffer;

          int m_nLen;

       public:

          A(){ m_cBuffer = new char[m_nLen]; }

          ~A() { delete [] m_cBuffer; }

       };

       A *a = new A[10];

       delete a;         //仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数 剩下的从a[1]到a[9]这9个用户自行分配的m_cBuffer对应内存空间将不能释放

       从而造成内存泄漏

       delete [] a;      //释放了a指针指向的全部内存空间 并且调用使用类对象的析构函数释放用户自己分配内存空间

       在   vc   中对于简单数据类型int,char等的数组使用delete还是delete[]是完全一样的,不过对于类的实例的数组来说就必须使用delete[],否则可能会引起该类的析沟函数不会被正确调用。

    总结:在不明确指针指向的是否是数组还是单个变量时,用delete[] p;来删除指针是最好的办法。不会引起上面说的间接内存泄露。

  • 相关阅读:
    [教你做小游戏] 只用几行原生JS,写一个函数,播放音效、播放BGM、切换BGM
    博客园商业化之路-开篇:开源的脚步,商业化的出路
    vim命令编辑完文件后,按ESC键退出编辑模式,无法进入命令模式解决方案
    基于RuoYi-Flowable-Plus的ruoyi-nbcio项目的formdesigner文件上传与回显处理
    安防监控/视频汇聚平台EasyCVR云端录像不展示该是什么原因?该如何解决?
    leetCode 21.合并两个有序链表
    WANem弱网环境模拟工具的使用探索
    SpringCloud学习(四)——Nacos注册中心
    基于随机无迹σ变异的改进HHO算法
    【后端速成 Vue】初识指令(上)
  • 原文地址:https://blog.csdn.net/u011555996/article/details/124869951