天天看點

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[]的差別