天天看点

C++基础---对象数组中delete与delete[]的区别1. 对象数组中delete与delete[]的区别

1. 对象数组中delete与delete[]的区别

1.1 释放动态分配的内存空间

  • C++中对new申请的内存的释放方式有delete和delete[]两种方式。

    (1)delete:释放new分配的单个对象指针指向的内存;

    (2)delete[]:释放new[]分配的对象数组指针指向的内存;

1.2 关于 new[] 和 delete[]分为两种情况

  • 基本数据类型分配和回收空间;
  • 自定义类型分配和回收空间(即对象数组的内存管理);

1.3 基本数据类型分配和回收空间

  • 针对内置类型(即基本数据类型)使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可,如:
    int *a = new int[];
    delete a;//正确
    <=>等价于
    delete[] a;//正确
               
  • 代码示例:
    #include <iostream>;
    
    using namespace std;
    int main()
    {
        int NUM = ;
    
        int *a1 = new int[NUM];
        cout<<a1<<endl;
        delete a1;
        cout<<"释放了a1的空间"<<endl;
    
        int *a2 = new int[NUM];
        cout<<a2<<endl;
        delete[] a2;
        cout<<"释放了a2的空间"<<endl;
    
        system("pause");
        return ;
    }
    =>
      释放了a1的空间
      
      释放了a2的空间
               

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

    它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间(在分配过程中系统会记录分配内存的大小等信息,此信息保存在结构体_CrtMemBlockHeader中,具体情况可参看VC安装目录下CRT\SRC\DBGDEL.cpp)

1.4 自定义类型分配和回收空间(即对象数组的内存管理)

  • 针对自定义类型使用new分配后的空间,若是数组形式的内存空间,两种方式效果截然不同,如:
    T *a = new T[];
    delete a;//错误,仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数,剩下的从a[1]到a[9]这9个用户自行分配的对应内存空间将不能释放 从而造成内存泄漏。
    <!=>效果截然不同
    delete[] a;//正确,调用使用类对象的析构函数释放用户自己分配内存空间并且释放了a指针指向的全部内存空间。
               
  • 错误程序示例:
    #include <iostream>;
    
    using namespace std;
    class T 
    {
    public:
        T() 
        {
            cout <<"构造T"<<endl;
        }
        ~T() 
        {
            cout <<"析构T"<<endl;
        }
    };
    int main()
    {
        int NUM = ;
    
        T *p1 = new T[NUM];
        cout<<p1<<endl;
        delete p1;//错误释放语句
        cout<<"释放了p1空间"<<endl;
    
        T *p2 = new T[NUM];
        cout<<p2<<endl;
        delete[] p2;//正确释放语句
        cout<<"释放了p2空间"<<endl;
    
        system("pause");
        return ;
    }
    =>构造T
      构造T
      构造T
      4754
      析构T
      程序崩溃了Debug Assertion Failed!
      Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
               
  • 正确程序示例:
    #include <iostream>;
    
    using namespace std;
    class T 
    {
    public:
        T() 
        {
            cout <<"构造T"<<endl;
        }
        ~T() 
        {
            cout <<"析构T"<<endl;
        }
    };
    int main()
    {
        int NUM = ;
    
        T *p1 = new T[NUM];
        cout<<p1<<endl;
        delete[] p1;//正确释放语句
        cout<<"释放了p1空间"<<endl;
    
        T *p2 = new T[NUM];
        cout<<p2<<endl;
        delete[] p2;//正确释放语句
        cout<<"释放了p2空间"<<endl;
    
        system("pause");
        return ;
    }
    =>构造T
      构造T
      构造T
      
      析构T
      析构T
      析构T
      释放了p1空间
      构造T
      构造T
      构造T
      
      析构T
      析构T
      析构T
      释放了p2空间
               
    注:在用这些类生成对象数组的时候,用delete[]来释放它们才是王道。

参考文献:

[1] 百度搜索关键字:delete与delete[]的区别