c++---c與c++的動態內存管理

c與c++動態內存管理

首先我們來看看它們都是怎麼使用的吧。

malloc

void *malloc( size_t size );

calloc

//num:開闢的這塊空間有多少個元素
//size:每個元素的字節數
void *calloc( size_t num, size_t size );

realloc

//memblock需要擴容的指針
//size 需要擴充到n個字節
void *realloc( void *memblock, size_t size );

new

new + 需要申請的類型

delete

delete + 指向需要銷燬的那塊空間的指針

new []

//申請一塊內存,用於存放數組
new + 類型[大小]

delete

delete[] + 指針
在C語言中是使用malloc來申請空間,用free來釋放空間                          
c語言中不止是有malloc還有calloc,realloc,它們都是c語言中用來動態開闢內存的。

那麼他們之間有什麼區別呢?

  • malloc:用來申請一塊空間,malloc(需要開開闢的空間的字節數),用malloc開闢的空間,沒有初始化,就只是一塊空間。
  • calloc: 開闢一塊空間,並且對這段空間進行初始化。自動將這段空間都初始化爲零。
  • realloc:在原來的空間上進行擴容。若是當前內存有足夠的空間可以開闢,那麼就直接在當前內存的後面開闢,若是內存不足,則需要再重新找一塊內存,開闢空間,將之前的值再拷貝過來。然後釋放之前的內存空間。

   如果申請成功,返回的都是當前內存的地址,若是申請失敗,則返回NULL。
   在不使用這段內存空間後,一定要記得釋放這段空間,用free(指向這段空間的指針)。如果不釋放,就會造成內存泄漏。表面看着沒有什麼影響,但是會一直佔着內存,直到程序結束。


   c++與c語言一樣,也有動態內存開闢的機制,支持程序員自己申請與釋放內存。
   在c++中就是使用new和delete,new是用來申請空間,delete用來釋放空間。
既然在c語言中已經有了動態開闢內存的機制,爲什麼在c++中還要引入new和delete呢?
   下面我們就來說一說malloc/free與new/delete的區別

  1. malloc/free是c/c++中的函數,而new/delete則是操作符。從它們的使用方式就可以看出來。malloc/free使用時需要有參數,參數必須得有括號。而new/delete則不需要用括號,後面直接跟需要創建的類型就可以。
  2. malloc/free只是負責開闢空間與釋放空間,new與delete則是還需要調用構造函數與析構函數。對開闢的空間要進行初始化,若是要銷燬,就需要調用析構函數,來清理空間。
  3. malloc/free需要自己提供需要開闢的字節數,並且返回值爲void*,這就需要程序員對接收這塊空間的變量類型確定,並且要強轉返回的類型爲想要的類型,不然就會出錯。但是new/delete只需要提供想要開闢的類型即可。而且返回的就是對應類型的指針。不需要再手動強轉。

他們的相同點就是都可以申請空間/釋放空間。
接下來,我們詳細的說明一下它們的用法

new / delete

它們是動態管理對象的。調用構造析構函數。
現在舉個例子來驗證一下:

#include<iostream>
using namespace std;
class AA
{
public:
    AA()
    {
        cout<<"AA()"<<endl;
    }
    ~AA()
    {
        cout<<"~AA()"<<endl;
    }
};
int main()
{
    AA *p1 = new AA;
    delete p1;
    return 0;
}

這裏寫圖片描述

從上面的這個例子能看出,new/delete在對自定義類型使用的時候,,會自動的調用它們的構造函數與析構函數。創建一個對象就會調用一次構造函數。銷燬一個對象的時候也會調用一次其析構函數。那麼new[]/delete[]是怎麼調用構造析構函數的呢?

 AA *p1 = new AA[3];
    delete[] p1;

new[/delete[的析構與構造的調用情況
   上面這段程序,創建了一個數組,這個數組時候一個存對象的數組,有三個元素。所以需要對每一個對象調用構造函數,並且清理的時候也需要調用三次析構函數。就出現了上圖的結果。


   上面介紹的就是new/delete,new[]/delete[]的簡單用法。接下來說一說它們的匹配使用問題。
   new/delete是一組,new[]/delete[]是一組。一定是要匹配使用,不可以打亂組合。否則可能會出現內存泄漏甚至程序崩潰。從上面說到的來看,new/delete都是隻調用一次,new[]/delete[]調用幾次取決於數組中的元素個數。所以,如果出現了不匹配使用,那麼調用構造函數與析構函數的次數也就不會匹配,那麼就會導致程序出問題。這就是不匹配使用的爲什麼會導致錯誤的原因。


   在c++中還有別的動態內存管理的接口。

  • operator new(size_t size)
  • operator delete(size_t size)
  • operator new[](size_t size)
  • operator delete[](size_t size)

operator new/operator delete是一組,匹配使用,負責開闢空間與釋放空間。它們的作用相當與c語言中的malloc與free,與它們的用法一樣,實際上,operator new/operator delete是malloc/free的一層封裝。
operator new[]/operator delete[]是一組,匹配使用,負責開闢連續的數組空間與釋放連續的空間。
這四個接口都是函數,不是操作符。看樣子是有點像new/delete的運算符重載,其實並不是。new/delete,new[]/delete[]是通過這四個對應的函數來獲取內存與釋放內存。它們不會調用對象的構造函數與析構函數來初始化對象與清理對象。
具體過程如下所示:
   調用構造函數是new操作符完成的,new又調用operator new開闢內存。而在operator new中有個malloc函數,是負責開闢空間。所以c++中的內存管理就是在c語言的基礎上進行了封裝與修改得到了c++中的內存管理機制。
new
new[n]是開闢一段連續的空間。這段連續的空間裏面存放的是相同的類型數據。new負責調用n次構造函數再調用operator new[],來開闢空間。與new一樣,底層實現還是malloc函數。
new[]
delete與new類似,delete操作符負責調用一次析構函數,再調用一次operator delete函數,operator delete負責清理空間,operator delete函數是free函數的封裝,所以,其實是free釋放的空間。
delete
delete[]這個操作符就有些不一樣了。因爲delete[]不需要寫具體數字,那麼,我們怎麼知道需要調用幾次析構函數呢?
   其實在new[]時,在開闢的空間前四個字節,存儲的是n。即當前這個數組中元素的個數。在需要delete這個數組時,只需向前讀四個字節,就可以知道當前數組的個數,即知道需要調用幾次析構函數。
delete[]

發佈了65 篇原創文章 · 獲贊 31 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章