3.4 動態記憶體分配 (dynamic memory)到目前為止,我們的程式中我們只用了宣告變數、陣列和其他物件(objects)所必需的記憶體空間,這些記憶體空間的大小都在程式執行之前就已經確定了。但如果我們需要記憶體大小為乙個變數,其數值只有在程式執行時 (runtime)才能確定,例如有些情況下我們需要根據使用者輸入來決定必需的記憶體空間,那麼我們該怎麼辦呢?
答案是動態記憶體分配(dynamic memory),為此c++ 整合了操作符new 和delete。
操作符new 和new[ ]操作符new的存在是為了要求動態記憶體。new 後面跟乙個資料型別,並跟一對可選的方括號[ ]裡面為要求的元素數。它返回乙個指向記憶體塊開始位置的指標。其形式為:
pointer = new type
或者pointer = new type [elements]
第乙個表示式用來給乙個單元素的資料型別分配記憶體。第二個表示式用來給乙個陣列分配記憶體。
例如:int * bobby;
bobby = new int [5];
在這個例子裡,作業系統分配了可儲存5個整型int元素的記憶體空間,返回指向這塊空間開始位置的指標並將它賦給bobby。因此,現在bobby 指向一塊可儲存5個整型元素的合法的記憶體空間,如下圖所示。
};刪除操作符delete既然動態分配的記憶體只是在程式執行的某一具體階段才有用,那麼一旦它不再被需要時就應該被釋放,以便給後面的記憶體申請使用。操作符delete 因此而產生,它的形式是:
delete pointer;
或delete [ ] pointer;
第一種表達形式用來刪除給單個元素分配的記憶體,第二種表達形式用來刪除多元素(陣列)的記憶體分配。在多數編譯器中兩種表示式等價,使用沒有區別, 雖然它們實際上是兩種不同的操作,需要考慮操作符過載overloading (我們在後面的section 4.2
節中將會看到)。
// rememb-o-matic
#include ?iostream.h?
#include ?stdlib.h?
int main ( ) {
char input [100];
int i,n;
long * l;
cout << "how many numbers do you want to type in? ";
cin.getline (input,100); i=atoi (input);
l= new long;
if (l == null) exit (1);
for (n=0; nnull是c++庫中定義的乙個常量,專門設計用來指代空指標的。如果這個常量沒有被預先定義,你可以自己定以它為0:
#define null 0
在檢查指標的時候,0和null並沒有區別。但用null 來表示空指標更為常用,並且更易懂。原因是指標很少被用來比較大小或被直接賦予乙個除0以外的數字常量,使用null,這一賦值行為就被符號化了。
ansi-c 中的動態記憶體管理dynamic memory in ansi-c操作符new 和delete 僅在c++中有效,而在c語言中沒有。在c語言中,為了動態分配記憶體,我們必須求助於函式庫stdlib.h。因為該函式庫在c++中仍然有效,並且在一些現存的程式仍然使用,所以我們下面將學習一些關於這個函式庫中的函式用法。
函式malloc這是給指標動態分配記憶體的通用函式。它的原型是:
void * malloc (size_t nbytes);
其中nbytes 是我們想要給指標分配的記憶體位元組數。這個函式返回乙個void*型別的指標,因此我們需要用型別轉換(type cast)來把它轉換成目標指標所需要的資料型別,例如:
char * ronny;
ronny = (char *) malloc (10);
這個例子將乙個指向10個位元組可用空間的指標賦給ronny。當我們想給一組除char 以外的型別(不是1位元組長度的)的數值分配記憶體的時候,我們需要用元素數乘以每個元素的長度來確定所需記憶體的大小。幸運的是我們有操作符sizeof,它可以返回乙個具體資料型別的長度。
int * bobby;
bobby = (int *) malloc (5 * sizeof(int));
這一小段**將乙個指向可儲存5個int型整數的記憶體塊的指標賦給bobby,它的實際長度可能是 2,4或更多位元組數,取決於程式是在什麼作業系統下被編譯的。
函式calloccalloc 與malloc 在操作上非常相似,他們主要的區別是在原型上:
void * calloc (size_t nelements, size_t size);
因為它接收2個引數而不是1個。這兩個引數相乘被用來計算所需記憶體塊的總長度。通常第乙個引數(nelements)是元素的個數,第二個引數 (size) 被用來表示每個元素的長度。例如,我們可以像下面這樣用calloc定義bobby:
int * bobby;
bobby = (int *) calloc (5, sizeof(int));
malloc 和calloc的另一點不同在於calloc 會將所有的元素初始化為0。
函式realloc它被用來改變已經被分配給乙個指標的記憶體的長度。
void * realloc (void * pointer, size_t size);
引數pointer 用來傳遞乙個已經被分配記憶體的指標或乙個空指標,而引數size 用來指明新的記憶體長度。這個函式給指標分配size 位元組的記憶體。這個函式可能需要改變記憶體塊的位址以便能夠分配足夠的記憶體來滿足新的長度要求。在這種情況下,指標當前所指的記憶體中的資料內容將會被拷貝到新的位址中,以保證現存資料不會丟失。函式返回新的指標位址。如果新的記憶體尺寸不能夠被滿足,函式將會返回乙個空指標,但原來引數中的指標pointer 及其內容保持不變。
函式 free這個函式用來釋放被前面malloc, calloc 或realloc所分配的記憶體塊。
void free (void * pointer);
注意:這個函式只能被用來釋放由函式malloc, calloc 和realloc所分配的空間。
你可以參考c++ reference for cstdlib
獲得更多關於這些函式的資訊。
動態記憶體分配
在c 中建立乙個物件時,我們必須要為這個物件申請一塊記憶體,而且要用建構函式對這塊記憶體進行初始化。c 中的new和delete相對於c的庫函式malloc和free在這方面有很大的優勢,所以我們主要講的是運算子new和delete。當用new來建立乙個物件時,它會自動在堆裡為物件分配記憶體並且為這...
動態記憶體分配
為什麼使用動態記憶體分配?c語言中的一切操作都是基於記憶體的 變數和陣列都是記憶體的別名,如何分配這些記憶體由編譯器在編譯期間決定 定義陣列的時候必須指定陣列唱的 而陣列長度是在編譯期就必須決定的 需求 程式執行的過程中,可能需要使用一些額外的記憶體空間 malloc和free malloc和fre...
動態記憶體分配
c的儲存類別有4種 自動的 auto 靜態的 statics 暫存器的 register 外部的 extern 全域性變數時分配在記憶體中的靜態儲存區 靜態區域性變數屬於靜態儲存類別,在靜態儲存區內分配儲存單元,是在編譯時賦初值的,只賦初值一次,在程式執行時它已有初值,以後每次呼叫函式時不再重新賦初...