1. 程式人生 > >動態分配記憶體 and malloc&new and 陣列的動態分配、初始化(memset)和撤銷(delete)

動態分配記憶體 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;

}