動態記憶體分配

2021-07-28 12:19:10 字數 3316 閱讀 4013

c語言中記憶體分配方式

1,從靜態全域性區分配

內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在,例如全域性變數,static變數

2,在棧上分配

在執行函式時,函式內區域性變數的儲存單元都可在棧上建立,函式執行結束時這些儲存單元自動釋放,棧記憶體分配運算內置於cpu的指令集中,效率高,但分配的記憶體容量有限

3,從堆上分配(動態記憶體分配)

程式在執行時用malloc和new申請任意多少的記憶體,程式設計師自己決定何時用free和delete釋放記憶體。動態記憶體的生命週期有使用者決定,使用靈活

c語言中與記憶體申請有關的函式主要有alloca,calloc,malloc,realloc,free等

1,alloca是向棧申請記憶體,無需釋放(用完馬上被釋放);

2,malloc分配的記憶體位於堆中,並且沒有初始化記憶體的內容,因此基本上malloc之後,呼叫memset來初始化這部分記憶體空間;

3,calloc則初始化這部分記憶體為0;

4,realloc是追加,是對已申請的記憶體空間進行大小的調整;

5,當乙個動態分配的記憶體塊不再使用時,應該呼叫free()把它歸還給可用記憶體池,記憶體被釋放後便不能被訪問。

這幾個函式的原型如下:

void* malloc(size_t size);

void* realloc(void* ptr,size_t new_size);

void* calloc(size_t num_elements,size_t element_size);

void free(void* pointer);

區別:

函式malloc()在記憶體的動態儲存區中分配一塊長度為size位元組的連續區域,引數size為所需記憶體空間的長度,返回該區域的首位址。他不能初始化所分配的記憶體空間(calloc函式可以做到),如果由malloc函式分配的記憶體空間原來沒有被使用過,則其中的每一位都可能是0,如果這部分記憶體曾經被分配過,則其中可能遺留有原先的資料,綜上,使用malloc函式的程式開始時能正常進行,但一段時間後可能會出現問題(記憶體空間已經被重新分配)。再乙個malloc()向系統申請分配的指定size個位元組的記憶體空間,返回型別是void*(未確定型別的指標),c,c++規定,void*型別可以強制轉換為任何其他型別的指標。

函式calloc()會將分配的記憶體空間中的每一位都初始化為0.

realloc()可以給指定的指標所指向的記憶體空間進行大小的調整,記憶體擴張不會引起內容的變化,而縮小會導致縮小的那部分其中的內容丟失。再乙個realloc()並不能保證調整後的記憶體空間和原來的記憶體空間位址相同,相反,realloc返回的指標很可能指向乙個新的位址(realloc()是從堆上分配記憶體的,當擴大一塊記憶體空間時,realloc()試圖直接從堆上現存的資料後面的那些位元組中獲得所需的位元組,如果夠則直接開闢,如果不夠則會使用堆上乙個足夠大的自由塊,現存的資料然後被拷貝至新的位址空間,而老塊則放回到堆上,這說明了乙個問題:原資料可能被移動。)。

總結

1,如果請求的記憶體分配失敗,malloc,calloc,realloc函式都返回的將是乙個null指標。因此對每個從malloc返回的指標都進行檢查,確保並非為null。錯誤的訪問分配記憶體之外的區域所引起的後果類似越界訪問乙個陣列,但這個錯誤可能破壞可用的記憶體池,引起程式失敗。如果乙個指標不是從早先的malloc等函式返回的,它不能作為引數傳遞給free函式。

2,你也不能只釋放一塊記憶體的一部分。

3,記憶體洩漏是指記憶體被動態分配之後,當他不再使用時未被釋放。記憶體洩漏會增加程式的體積,有可能導致程式或系統的崩潰。但記憶體洩漏僅僅指程式在執行時,程式退出後,os將**所有的資源。

c++動態記憶體分配

1,c++通過new和delete來管理動態記憶體分配(new和delete動態管理物件,new和delete動態管理記憶體陣列)

2, int* p0 = new int;   //動態分配4個位元組(1個int)的記憶體空間

int* p1 = new int(3);//動態分配4個位元組(1個int)的記憶體空間,初始化為3

int* p2 = new int[3];//動態分配12個位元組(1個int)的記憶體空間

delete   p1;

delete p2;

注:malloc/free,new/delete,new/delete一定要匹配使用,否則可能出現記憶體洩漏或程式崩潰的問題。

3,記憶體管理

int a = 1;

static int b = 1;

void test()

全域性變數,靜態全域性變數,區域性變數,靜態區域性變數的區別?

全域性變數與靜態全域性:主要是連線屬性不同,靜態全域性變數只能在當前原檔案內使用。而全域性變數**都能使用。

區域性變數與靜態區域性變數:區域性變數建立在棧上,靜態區域性變數建立在靜態區,這導致他們生命週期不同,靜態區域性建立好不再銷毀,直到程式結束。而區域性變數出了它的作用域就自動銷毀。

4,深入理解c++動態記憶體管理

malloc/free和new/delete的區別:

a,他們都是動態記憶體管理的入口; 

b,malloc/free是c/c++標準庫的函式,new/delete是c++操作符;

c,malloc/free只是動態分配記憶體/釋放記憶體,而對於自定義型別,new/delete除了分配空間還能呼叫建構函式和析構函式進行初始化與清理。

d,malloc//free需要手動計算型別大小且返回值為void* ,new/delete可自己計算型別的大小,返回對應型別的指標。

5,c++的其他記憶體管理介面

void* operator new(size_t size);

void* operator delete(size_t size);

void* operator new(size_t size);

void* operator deletot(size_t size);

注:以上不是運算子的過載。。。實際上只是malloc/free的一層封裝,用法沒變,他們只負責分配空間/釋放空間,不會呼叫建構函式/析構函式來進行初始化或清理物件。

6,new 做了兩件事:1,呼叫operator new分配空間;2,呼叫建構函式初始化物件

new[n]做了兩件事:1,呼叫operator new;2,呼叫n次建構函式分別初始化每個物件。

7,定位new表示式

這是在已分配的原始記憶體空間中呼叫建構函式初始化乙個物件。

new(place_address)type;

new(place_address)type(initializer_list);

例子:int main()

動態記憶體分配

在c 中建立乙個物件時,我們必須要為這個物件申請一塊記憶體,而且要用建構函式對這塊記憶體進行初始化。c 中的new和delete相對於c的庫函式malloc和free在這方面有很大的優勢,所以我們主要講的是運算子new和delete。當用new來建立乙個物件時,它會自動在堆裡為物件分配記憶體並且為這...

動態記憶體分配

為什麼使用動態記憶體分配?c語言中的一切操作都是基於記憶體的 變數和陣列都是記憶體的別名,如何分配這些記憶體由編譯器在編譯期間決定 定義陣列的時候必須指定陣列唱的 而陣列長度是在編譯期就必須決定的 需求 程式執行的過程中,可能需要使用一些額外的記憶體空間 malloc和free malloc和fre...

動態記憶體分配

c的儲存類別有4種 自動的 auto 靜態的 statics 暫存器的 register 外部的 extern 全域性變數時分配在記憶體中的靜態儲存區 靜態區域性變數屬於靜態儲存類別,在靜態儲存區內分配儲存單元,是在編譯時賦初值的,只賦初值一次,在程式執行時它已有初值,以後每次呼叫函式時不再重新賦初...