動態分配記憶體 and malloc&new and 陣列的動態分配、初始化(memset)和撤銷(delete)
在計算機的系統中有四個記憶體區域:
1)棧:在棧裡面儲存一些我們定義的區域性變數和形參。
2)字元常量區:主要儲存一些字元常量,比如:char *p_str="cat",其中"cat"就儲存於字元常量區裡。
3)全域性區:在全域性區裡儲存一些全域性變數和靜態變數
4)堆:主要是通過動態分配的儲存空間,即動態分配記憶體空間。
棧是執行緒相關的 一個執行緒會建立一個棧,函式中的區域性變數 實際上是在棧裡面的 函式返回後 就從棧中pop出來,棧的容量是有限的 超過一定大小就棧就會擊穿了,比如你寫了深層次的遞迴,然後再函式中使用大量的陣列,很容易就擊穿了
堆是動態儲存空間,一個程序預設只有一個堆,程序中所有的執行緒都共享這個堆的空間,所以你在一個執行緒中從堆中分配記憶體,再另一個執行緒中也可以訪問,同時堆也更容易擴充套件和交換資料
為什麼要動態分配記憶體?
一是受棧空間的限制,二是不想浪費記憶體。
動態分配和靜態分配的比較:
動態分配就是基於現實考慮,在需要時才分配你需要數量的記憶體(當然你申請的記憶體什麼時候用完,只有你才知道,系統不會浪費時間給你猜的)。
一般的靜態變數都是放在棧裡(按順序排列好,訪問也最快,當然在回收前是不能改變順序和已分配的數量的,作用域結束就回收),受棧的限制。
malloc 和 new
1)new 是c++中的操作符,malloc是c 中的一個函式
2)new 不止是分配記憶體,而且會呼叫類的建構函式,同理delete會呼叫類的析
構函式,而malloc則只分配記憶體,不會進行初始化類成員的工作,同樣free也不
會呼叫解構函式
3)記憶體洩漏對於malloc或者new都可以檢查出來的,區別在於new可以指明是那
個檔案的那一行,而malloc沒有這些資訊
4)new 和 malloc效率比較
new 有三個字母, malloc有六個字母
new可以認為是malloc加建構函式的執行。
new出來的指標是直接帶型別資訊的。
而malloc返回的都是void指標
陣列的動態分配(new)、初始化(memset)和撤銷(delete)
一維陣列:
malloc的例子:
int* pB2 = (int*)malloc(20 * sizeof(int));
if(pB2 == NULL) return 0;
memset(pB2,-1,20 * sizeof(CvBlob)); //初始化為-1
/**************/
if(pB2)
{
free(pB2);
pB2 = NULL;
}
new 的例子:
int* pB2 = new int[20];
/****************/
delete []pB2;
pB2 = NULL;
二維陣列:
二維陣列(n行m列)利用new來進行動態分配實際上相當於對n個m元陣列進行動態
分配。
int **array;
array=new int *[10];
for(int i=0;i<10;i++)
array[i]=new int [5];
上面的操作完成了一個10行5列的二維陣列array[10][5]的動態分配,可以看到
我們先動態分配一個10單元的陣列的指標的指標的首地址給**array,然後再對
其每個首地址進行遍歷,同時完成一個5單元的陣列的動態分配,並把首地址給
array[i],從而完成了二維陣列array[10][5]的動態分配。
因為memset只能完成一個一維陣列的初始化,因此最好的辦法就是和二維數
組的動態分配結合起來,new一個,memset一個。
int **array;
array = new int[10];
for(int i=0;i<10;i++)
{
array[i] = new int[5];
memset(array,0,5*sizeof(int));
}
二維陣列的撤銷
for(int i=0;i<10;i++)
{
delete []array[i];
}
delete []array;
三維陣列用一個例子說明:
#include <stdio.h>
#include <memory.h>
#define size1 5
#define size2 10
#define size3 15
int main()
{
int *** arr;
int i,j,k;
/////////////////// 動態開闢 相當於arr[size1][size2][size3]
arr = new int**[size1];
for (i = 0; i < size1; i ++) {
arr[i] = new int*[size2];
for (j = 0; j < size2; j ++) {
arr[i][j] = new int[size3];
}
}
/////////////////// 用for迴圈初始化
for (i = 0; i < size1; i ++) {
for (j = 0; j < size2; j ++) {
for (k = 0; k < size3; k ++) {
arr[i][j][k] = i * j * k;
}
}
}
for (i = 0; i < size1; i ++) {
for (j = 0; j < size2; j ++) {
for (k = 0; k < size3; k ++) {
printf("i*j*k=%d*%d*%d=
%d/n",i,j,k,arr[i][j][k]);
}
}
}
/////////////////// 用memset,如果是靜態int arr[][][]的話,
直接memset(arr,0,sizeof(arr));陣列初始化為0
for (i = 0; i < size1; i ++) {
for (j = 0; j < size2; j ++) {
memset(arr[i][j],-1,sizeof(int) * size3);
}
}
for (i = 0; i < size1; i ++) {
for (j = 0; j < size2; j ++) {
for (k = 0; k < size3; k ++) {
printf("i,j,k=%d,%d,%d=
%d/n",i,j,k,arr[i][j][k]);
}
}
}
///////////////////// 釋放記憶體
for (i = 0; i < size1; i ++) {
for (j = 0; j < size2; j ++) {
delete[] arr[i][j];
}
delete[] arr[i];
}
delete[] arr;
return 0;
}