說起new和delete,了解過c++的人應該都知道吧,它是用來分配內存和釋放內存的兩個操作符。與c語言中的malloc和free類似。
c語言中使用malloc/calloc/realloc/free進行動態內存分配,malloc/calloc/realloc用來在堆上分配空間,free將申請的空間釋放掉。
malloc:
void FunTest()
{int *pTest = (int*)malloc(10*sizeof(int)); //開辟10個int型的空間大小if(pTest != NULL){free(pTest);pTest = NULL;}
}
calloc:
void FunTest()
{int *pTest = (int*)calloc(10,sizeof(int)); //分配10個int型的內存塊,并將其初始化為0if(pTest != NULL){free(pTest);pTest = NULL;}
}
realloc:
void FunTest()
{int *pTest = (int*)malloc(10*sizeof(int)); realloc(pTest,20*sizeof(int)); //改變原有空間大小,若不能改變則會新開辟一段空間,并將原有空間的內容 拷貝過去,但不會對新開辟的空間進行初始化free(pTest);
}
這里要注意的一點是,為什么分配了空間之后,必須要用戶手動去free掉呢,是因為malloc、calloc、realloc都是在堆上分配的,堆上分配的空間必須由用戶自己來管理,如果不釋放,就會造成內存泄漏。而棧上分配的空間是由編譯器來管理的,具有函數作用域,出了函數作用域后系統會自動回收,不由用戶管理,所以不用用戶顯式釋放空間。
對于內存泄漏,我介紹一下我所見過的內存泄漏吧:
(1)申請內存但并未釋放。
void FunTest()
{int *pTest1 = (int*)malloc(10*sizeof(int));*pTest1 = 0;
}
(2)程序邏輯錯誤,這里引出兩個問題。
①同一塊空間釋放兩次,導致崩潰;
②有一塊空間沒有釋放,以為釋放了,導致內存泄漏。
void FunTest()
{int *pTest1 = (int*)malloc(10*sizeof(int));int *pTest2 = (int*)malloc(10*sizeof(int));pTest1 = pTest2;free(pTest1);free(pTest2);
}
(3)程序的誤操作,將堆破壞。申請的空間不足以賦值,釋放導致崩潰。
void FunTest()
{char *pTest1 = (char*)malloc(5);strcpy(pTest1,"hello world");free(pTest1);
}
(4)當釋放時傳入的地址和分配時的地址不一樣時,會導致崩潰。
void FunTest()
{int *pTest1 = (int*)malloc(10*sizeof(int));assert(pTest1 != NULL);pTest1[0] = 0;pTest1++; //地址向后移動了一位free(pTest1);
}
上述簡單的介紹了一下c語言中動態內存管理的類型,下面講解一下c++中的動態內存管理。
c++中是通過new和delete操作符進行動態內存管理的。
先用一張圖簡單的說明一下new和delete的含義:
記住:new和delete就像malloc和free一樣,都要成對使用哦。
我們再看一個這樣的表達式:
string *s = new string("a value"); //分配并初始化一個string對象
string *str = new string[10]; //分配10個默認初始化的string對象
這兩個new表達式,一個是分配一個對象,一個是分配對象數組。內部實現也是截然不同。
這是string *s = new string("a value"); 這句表達式內部的實現:
我們可以看出new內部的調用順序:(初始化一個對象時)
new內部的調用順序:(初始化若干個對象時)
同樣地,delete對象時,調用順序為:(delete單個對象時)
delete對象時,調用順序為:(delete多個對象時)
接下來,看一下動態內存分布圖:
new和delete與malloc和free一樣,都是存在堆上的。那么,二者有什么差別呢?
·?總結new/delete和malloc/free的區別和聯系:
1. 它們都是動態管理內存的入口。
2. malloc/free是C/C++標準庫的函數,new/delete是C++操作符。
3. malloc/free只是動態分配內存空間/釋放空間。而new/delete除了分配空間還會調用構造
析構函數進行初始化與清理(清理成員)。
4. malloc/free需要手動計算類型大小且返回值為void*,new/delete可自己計算類型的大小
對應類型的指針。
5.new/delete的底層調用了malloc/free。
6.malloc/free申請空間后得判空,new/delete則不需要。
7.new直接跟類型,malloc跟字節數個數。