C C 分配記憶體的那些事

2021-09-05 10:03:41 字數 2982 閱讀 2115

首先需要知道,編譯器給變數分配的記憶體分為三部分:靜態儲存區域、棧、堆。

靜態儲存區:主要儲存全域性變數和靜態變數。

棧:呼叫函式相關的變數、位址等,底層對棧提供支援,棧的大小遠小於堆的大小,向負方向生長,限定大小。

堆:儲存動態生成的變數,操作由c/c++函式庫提供,效率低於棧,向正方向生長,無限大小(32位可達4g)。

1.使用new與delete

classname *object=new classname(param);//單個物件

delete object;

object=null;

int *a = new int[5];//陣列

delete a; //釋放int陣列空間

使用new,這個時候系統會呼叫建構函式,此時c++是在堆上開闢了一塊空間來建立物件的,c++用new建立物件時返回的是乙個物件指標(要訪問new所開闢的結構體空間,無法直接通過變數名進行,只能通過賦值的指標進行訪問),物件指標object此時指向乙個classname的物件,c++分配給object的僅僅是存放指標值的空間。需要注意的是,使用完這個物件後,需要手動delete刪除,否則在整個程式生命週期內這個物件都將會占用記憶體,在需要反覆新建物件的工程中,長此以往將會造成記憶體洩漏。delete物件時會呼叫其析構函式,delete結束後指標需要指向null,否則可能誤用此指標。

注意:該方法建立的物件呼叫類方法時,必須用「->」,而不能用「.」。

2.使用建構函式(顯式呼叫和隱式呼叫)

class rec

;main()

用兩種方法建立了乙個myrec物件,實際上這兩種方式是一樣的,一種是顯示呼叫,一種是隱式呼叫,此時如果列印出sizeof(myrec),會得到 8 這個結果。因為myrec中有2個int型別的資料成員,乙個int成員佔4個位元組,所以myrec物件佔8個位元組。

這種方法建立的物件,記憶體分配是分配到棧中的,由c++預設建立和撤銷,自動呼叫建構函式和析構函式

注意:該方法建立的物件呼叫類方法時,必須用「.」,而不能用「->」如myrec.getarea()。

3.使用malloc()與free()

先來看下面的例子:

char *p;//1

p = (char *)malloc(10*sizeof(char));//2

if(p!=null) return;

memset(p,0,10*sizeof(char));//3

stpcpy(p,"come on");//4

p =(char *)realloc(p,20*sizeof(char));//5

if(p!=null) return;

strcat(p,",baby!");//6

free(p);//7

(1)定義乙個char*型指標變數p

(2)為p分配10個位元組的記憶體空間,若申請失敗則退出

(3)用0填充這個記憶體空間

(4)複製"come on" 字串到p指向的記憶體空間

(5)將p指標指向的記憶體空間再擴大20個位元組,若申請失敗則退出

(6)將",baby!"字元複製在p指向空間字串的後面

(7)釋放p指向的空間

*其中引數size_t size表示動態記憶體分配空間的大小,以位元組為單位,c++是在堆上開闢了一塊空間來建立物件的。

size_t 是typedef重定義的型別,重定義這樣資料型別的作用就是讓使用者一目了然,指示使用者這個引數表示乙個長度,在size後加上t,表示是整型相關資料型別的,以後看到***_t的型別,通常都是整型相關資料型別重定義。

malloc()函式的返回值是乙個指標,或者說是分配後記憶體空間的首位址, 如果malloc()函式申請空間成功則返回一段記憶體空間的首位址,失敗則返回null,失敗的原因可能是記憶體不足,為了防止後續的操作出錯,此處申請完記憶體後需要判斷是否申請成功。malloc返回值的型別是void* ,所以在呼叫malloc時要顯式地進行型別轉換,將void * 轉換成所需要的指標型別。

void memset(void s,int c,size_t n)

此函式將已開闢記憶體空間 s 的首 n 個位元組的值設為值 c。一般用在對定義的字串進行初始化為『 』或『/0』,此處為了防止分配的記憶體存在無關內容,首先對其進行清空操作。

void realloc(void mem_address, unsigned int newsize)

功能為改變mem_address所指記憶體區域的大小為newsize長度。如果重新分配成功則返回指向被分配記憶體的指標,否則返回空指標null。此處將原申請空間繼續擴大了。

void free(void ptr)*

功能為釋放掉指定的記憶體空間,其中void *ptr是記憶體空間的首位址,與malloc成對使用。

最後再列一些new與malloc的區別:

1.首先當然是編譯環境的區別,在c++中,兩者都可以使用,而在c中是不支援new的;

2.失敗時的區別,當new失敗時會丟擲bac_alloc異常,而malloc失敗時返回的是空指標;

3.返回值的區別,new返回的指標是與物件匹配的並不需要轉換,而malloc返回的是void型別指標,需要強轉;

4.new和delete會自動呼叫建構函式和析構函式,但是malloc和free不會;

5.malloc可利用realloc重新分配記憶體,new不可以;

6.new的使用比malloc簡單,內部已經實現了大小的計算、型別轉換等工作,而malloc使用時需要計算大小及進行型別轉換;

7.malloc是標準庫函式,new是c++的運算子。所有new可以被過載,但malloc不可以,malloc需要庫函式的支援,new不需要;

8.malloc可利用realloc重新分配記憶體,new不可以;

9.new有明確的方式處理陣列的分配,即new,釋放也有delete,malloc沒有。

記憶體那些事

linux中的free m可以檢視當前的記憶體使用情況 yejianfeng iz23fsd free m total used free shared buffers cached mem 7869 7737 132 0 489 4419 buffers cache 2828 5040 swap ...

記憶體的那些事

堆 heap 為程式儲存的一塊記憶體區域,用來儲存那些在執行時才知道其存在與大小的資料 程式能夠從堆中分配記憶體給這些元素 在用完之後,應該釋放掉這些記憶體。堆中所有的的東西都是匿名的 不能按名字直接訪問只能通過指標間接的訪問 棧 stack 為程式儲存的一塊記憶體區域,用來儲存狀態資料,例如 過程...

C C 記憶體分配

1 c c 記憶體分配 1 棧區 由編譯器自動分配和釋放,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。2 堆區 一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時可能由os 注意它與資料結構中的堆是兩回事。3 全域性 靜態 資料區 全域性變數和靜態變數的儲存是放在一塊...