zoukankan      html  css  js  c++  java
  • delete和delete[ ]的区别点

    关于动态申请的内存,分两种情况:基本数据类型的分配和自定义数据类型的分配。两者不同。

    1、基本数据类型
    对于基本数据类型,假如有如下代码

    int *a = new int[10];

    ...

    delete a; // 方式1

    delete [ ] a; //方式2

    肯定会不少人认为方式1存在内存泄露,然而事实上是不会!针对简单的基本数据类型,方式1和方式2均可正常工作,因为:基本的数据类型对象没有析构函数,并且new 在分配内存时会记录分配的空间大小,则delete时能正确释放内存,无需调用析构函数释放其余指针。因此两种方式均可。

    2、自定义数据类型
    这里一般指类,假设通过new申请了一个对象数组,注意是对象数组,返回一个指针,对于此对象数组的内存释放,需要做两件事情:一是释放最初申请的那部分空间,二是调用析构函数完成清理工作。对于内存空间的清理,由于申请时记录了其大小,因此无论使用delete还是delete[ ]都能将这片空间完整释放,而问题就出在析构函数的调用上,当使用delete时,仅仅调用了对象数组中第一个对象的析构函数,而使用delete [ ]的话,将会逐个调用析构函数。

     

     有如下代码:

    #include <iostream>;
    using namespace std;

    class 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; //输出P1的地址
    // delete[] p1;
    delete p1;

    cout << endl;

    T* p2 = new T[NUM];
    cout << p2 << endl; //输出P2的地址
    delete[] p2;

    return 0;
    }

    大家可以自己运行这个程序,看一看 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分配的单个对象指针指向的内存
    delete[] 释放new分配的对象数组指针指向的内存
    那么,按照教科书的理解,我们看下下面的代码:

    int *a = new int[10];
    delete a;        //方式1
    delete [] a;     //方式2

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

    下面给出总结性说明:

    针对简单类型

    使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可
    如:

    int *a = new int[10];
    delete a;
    delete [] a;

    此种情况中的释放效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数,它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间
    (在分配过程中 系统会记录分配内存的大小等信息,此信息保存在结构体_CrtMemBlockHeader中具体情况可参看VC安装目录CRTSRCDBGDEL.cpp)

    针对类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指针指向的全部内存空间

    总结

    对于像int/char/long/int*/struct等简单数据类型、由于其为基本数据类型没有析构函数,所以使用delete与delete []相同,两者都会释放申请的内存空间,不会有内存泄漏。

    当new申请的是C++对象数组时,delete和delete[]差别就很大了,delete只会析构一个对象,而delete[]可以逐一调用数组中的析构函数。

    delete ptr 代表用来释放内存,且只用来释放ptr指向的内存。
    delete[] rg 用来释放rg指向的内存,还逐一调用数组中每个对象的destructor

    建议

    为了养成良好的编程习惯,new 和 delete 配套,new[] 和delete[]配套使用。

    delete和delete[ ]的区别

  • 相关阅读:
    【抓包知识】01_tcpdump安装及使用
    【jmeter知识】03_jmeter接口报Read timed out +ng日志499分析
    【nginx知识】01_nginx日志请求到达时间$time_local、请求处理时间request_time
    【研发过程质量分析可视化】剩余需求实现(数据处理、数据可视化)
    【研发过程质量分析可视化】需求1(获取待分析缺陷清单)实现
    【研发过程质量分析可视化】需求文档
    【jmeter知识】01_接口响应时间(Connect Time、Latency、Sample Time)
    【python解题笔记20210318】CodeWars:RGB To Hex Conversion
    生成MD5加密
    StringBuilder--拼接Sql语句防Sql注入
  • 原文地址:https://www.cnblogs.com/klb561/p/15238897.html
Copyright © 2011-2022 走看看