• 文章
  • C/C++ 中的動態分配
釋出
2008年2月19日 (最後更新: 2008年2月19日)

C/C++ 中的動態分配

評分: 3.7/5 (41 票)
*****
它是什麼
----------

動態分配是 C/C++ 中記憶體的自動分配。與將資料載入到程式的資料段的宣告不同,動態分配會在程式的堆疊(分配給該程式的特定 RAM 區域)上建立新的可用空間。

它透過兩個函式(C 中)和兩個運算子(C++ 中)來實現
malloc 和 free,new 和 delete。

為什麼使用它
--------------

動態分配可能非常有用。例如,一個動態大小的陣列

假設 size 是一個變數(它不是定義為常量)。如果嘗試這樣做,編譯器會報錯
兩個版本
 
int array[size];


您可以做的是動態分配此記憶體。例如
C 版本
1
2
int *array;
array=(int *) malloc(size*sizeof(int));

C++ 版本
1
2
int *array;
array=new int[size]l



注意
由於這些資料被推送到堆疊而不是段,因此存在記憶體洩漏的可能性。記憶體洩漏是指分配的記憶體未在程式返回之前釋放。例如,要安全地釋放剛建立的陣列(並正常返回程式)
C 版本
 
free(array);

C++ 版本
 
delete [] array


另一個特別的注意:delete 後面的括號只有在你最初分配了一個數組時才需要。



動態分配對於使用連結串列是必要的。假設已宣告自引用的結構 Node,其中 nextptr 是連結
C 版本
1
2
3
4
5
6
7
struct Node *newptr;
newptr=(struct Node *) malloc(sizeof(Node));
/*We'll insert this into this linked list just
 at the second item, assuming topptr is the name
 of the top of this list.*/
newptr->nextptr=topptr->nextptr;
topptr->nextptr=newptr;

C++ 版本
1
2
3
4
5
Node *newptr;
newptr=new Node;
//We'll insert this as the second item, using topptr.
newptr->nextptr=topptr->nextptr;
topptr->nextptr=newptr;


當然,在以上兩個示例中,結構 Node 中沒有使用其他成員,這違背了連結串列的初衷。釋放節點
C 版本
1
2
3
4
5
6
7
struct Node *tempptr;
/*The node we'll free is, again, the second.*/
tempptr=topptr->nextptr;
/*We'll unbind this node first, so as not to lose all of the rest of the list with it.*/
topptr->nextptr=tempptr->nextptr;
/*It's free, get rid of it.*/
free(tempptr);

C++ 版本
1
2
3
4
5
6
7
Node *tempptr;
//We'll get the second node again.
tempptr=topptr->nextptr;
//Unbind this node.
topptr->nextptr=tempptr->nextptr;
//Get rid of it.
delete tempptr;


如何使用它
-------------

C 函式的語法是
1
2
3
#include <stdlib.h>

void *malloc(size_t size)

前幾個示例中的型別轉換是必要的,因為 malloc 返回 void 指標。
1
2
3
#include <stdlib.h>

void free(void *);

這不需要型別轉換;任何傳遞的引數都會被隱式降級。

C++ 中的運算子是
 
NewAlloc=new Type;

C++ 會自動為您進行型別轉換。
1
2
3
4
       //If this is an array
delete [] NewAlloc;
       //Otherwise
delete NewAlloc;


更進一步
-------------

vector 和 list 等幾個類使用了此功能。實現您自己的!

理解本文需要對指標和陣列(及其關係)有深入的瞭解。我知道,我應該把這個放在最上面。

定義一個類(我將其命名為 SafeSpot),它將在物件銷燬時自動處理其中定義的記憶體的釋放。這將消除所有那些意想不到的記憶體洩漏。您可能希望為該類的不同分配範圍嘗試不同的範圍(不要讓臨時函式物件存在於整個程式中)。

請回復,告訴我您對這篇文章的看法!
謝謝,
Graham Northup