c++內存管理new和delete運算符

我們先了解計算機中的內存在使用中被分爲下面幾部分:
在這裏插入圖片描述

內存佈局

棧:也叫堆棧,系統自動分配的空間,只要不特殊聲明,系統自動在棧上給變量和函數分配內存。棧是自頂向下增長的
堆:可使用動態內存分配的方式申請堆空間,當數據量較大時,棧空間有限,可在堆上申請空間存放;用完需要手動釋放!
常量區:用於存放程序中使用到的常量
代碼區:存放可執行代碼,在執行過程避免頻繁的讀取磁盤
作爲開發者,我們在程序中只需要管理的就是內存中的堆空間了,在c語言中我們使用一組函數來進行管理:c語言內存管理函數,那麼在c++中我們會有更好用的內存管理方式嗎?

new和delete的使用

肯定是有的,在c++中存在new和delete這兩個運算符專門用於內存管理,那麼這兩個運算符是如何使用的?

  int main()    
  {                       
      int* pi=new int;         
      int* pi1=new int(19);    
      int* arr=new int[10];    
      int i=0;             
      for(i=0;i<10;i++)    
      {    
          arr[i]=i;    
          cout<<arr[i]<<" ";                                                                                                          
      }                         
      cout<<endl;                                
      cout<<"*pi:"<<*pi<<" pi1:"<<*pi1<<endl;    
      //delete[] arr;                            
      delete arr;        
      delete pi;     
      delete pi1;    
      return 0;      
  } 

運行結果:
在這裏插入圖片描述
上面的關於new的使用:

  1. 爲一個類型數據在堆上分配空間 : new 類型名
  2. 爲一個類型數據在堆上分配空間並初始化爲給定初值:new 類型名(初值)
  3. 爲一個數據開闢一定個數的空間: new 類型名 [數據個數]

其中注意int* pi1=new int(19); 是開闢int類型的空間並給初值爲19,並不是開闢了19個int類型的空間。
使用完new出來的空間使用完以後就一定要記得使用delete對其分配的空間進行釋放:

  1. 釋放單個類型數據 :delete 類型指針名
  2. 釋放整個數組空間:delete[] 數組指針名

注意:對於數組空間的釋放,delete的使用稍有不同,當數組的數據類型爲基本類型時delete和delete[]都可對其進行釋放,但當數組的數據類型爲自定義類型時,delete在使用時只釋放了arr[0]的空間,那麼就不是我們想要的結果了,所以只能用dalete[] 的方式釋放

c++相對於c語言中的內存管理函數有何優勢?

new和delete相對於c語言中的malloc、free等函數來講,new和delete的同時會調用構造和析構函數,並且加入了分配失敗的異常機制,這樣new和delete在使用起來就非常方便,有大佬模擬了這兩個運算符的內部實現,供大家學習一下:new和delete的使用
我們通過學習可以看到new和delete還是通過調用malloc和free來分配和釋放內存空間,但是更加便利的是它們會自動調用構造和析構函數
如果數據類型爲基本類型,那麼是不需要調用構造函數和析構函數的,只有當數據類型爲自定義類型時,纔會調用構造函數和析構函數。
當開闢或釋放自定義類型的數組數據時,開闢了N個數據時,就調用了N次構造函數和N次析構函數。

new定位表達式

當頻繁的分配空間時,我們就會頻繁的調用malloc,這樣機會導致效率降低;new定位表達式則會提前分配好的空間上調用構造函數初始化,不用再次分配空間,以提高效率。

  int main()    
  {    
      char* buffer=new char[1024];//內存池    
      size_t size=0;           
      Data* pd=new(buffer+size)Data(2015,2,22);//在內存池中分配實例化    
      size+=sizeof(Data);    
      Data* pd2=new(buffer+size)Data(2019,2,22);    
      cout<<(void*)buffer<<endl<<pd<<endl<<pd2<<endl;    
        
      pd2->~Data();    
      pd->~Data();  
      //delete buffer;    
      delete[] buffer;                         
      return 0;     
  } 

運行結果:
在這裏插入圖片描述
通過new定位表達式申請的空間實際並沒有開闢新的空間,new(指針)類型申請的地址一般是括號裏指針保存的地址,然後調用構造函數,所以無需delete釋放,如果要釋放,可以通過顯示調用析構函數的方式釋放。例:pd->~Data();
那麼如果delete pd之後會出現問題嗎?當然,我們在delete pd會將定位表達式分配給pd的那部分內存釋放,然而當你在定位表達式適用完之後釋放預先分配的空間時,那這塊空間就被重複釋放。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章