c++動態記憶體管理

來源:互聯網
上載者:User

標籤:oc指標   技術   應該   接受   返回   需要   清理   new   自動   

一、記憶體的簡要瞭解

說到記憶體,很多人應該都多多少少有點瞭解了,我們在這再稍微多說幾句:

  一般我們可以把記憶體理解為三個部分:靜態區,棧,堆。有些朋友搞不清到底什麼是棧什麼是堆,堆棧有多人會認為是堆和棧,兩個放在一塊。其實不然,其中我們口中講的堆棧就是棧,而不是堆。堆的英文是heap ;棧的英文是stack(也翻譯為堆棧)。

 

儲存內容:

  靜態區:儲存自動全域變數和static變數(包括static全域和局部變數)。靜態區的內容在整個程式的生命週期內都存在,有編譯器在編譯的時候分配(資料區段(儲存全域資料和待用資料)和程式碼片段(可執行檔代碼/唯讀常量))。

  棧:儲存局部變數。棧上的內容只在函數範圍記憶體在,當函數運行結束的時候,這些內容也會自動銷毀。其特點是效率高但是空間大小有限。

  堆:由malloc系列函數或者new操作符分配的記憶體。其生命週期由free和delete決定。在沒有釋放之前一直存在,直到函數結束。其特點是使用靈活,空間比較大,但容易出錯。

 

  我們用一張圖來簡單看下:   值得注意的一點是:程式碼片段中儲存的是可執行檔代碼和唯讀常量,很多人看到程式碼片段就認為裡面只有代碼,資料區段裡面才是儲存資料的,其實不是這樣的。 

二、malloc、calloc、realloc

三者的簡單對比:

malloc   函數原型:(void*)malloc(unsigned size);(位元組數)

malloc函數在記憶體中開闢的是一塊連續的空間,size是所需要空間的長度,開闢的大小為size*參數類型,開闢完之後返回這塊空間的首地址。

 

calloc    函數原型:void* calloc(size_t numElements, size_t sizeOfElements);(元素的個數, 單個元素的位元組數)

和malloc相似,它也是開闢一塊連續的空間,空間的大小為:元素的個數*單個元素的位元組數。

 

realloc     函數原型:void* realloc(void* ptr, unsigned newsize);(地址,位元組數)

給一個已經分配地址的指標重新分配空間,參數ptr為原有的空間指標,newsize為重新申請的地址長度。它與malloc的區別就是如果你給的指標是NULL,那麼你使用的就是malloc,如果你給出的指標是一個已經分配了地址的指標(ptr),那麼你使用的就是realloc。

 

區別:

(1)函數malloc不能初始化所分配的空間,而函數calloc能,也就是說,如果由malloc函數分配的空間原來沒有被分配過,則其中每一位都可能是0;反之,如果這一塊資料區塊原來被分配過,那裡面可能遺留著各種各樣的資料。所以,當你在使用malloc開闢一塊新空間的時候,要重新初始化那一塊空間(一般調用memset函數來初始化空間)。否則在多次釋放、開闢之後,可能會出現使用錯誤。

(2)calloc函數會將所分配的記憶體空間中的每一位都初始化為0(這也是它和malloc的主要不同處之一)。也就是說,如果你是為字元類或者整形類的元素分配空間,那麼這些元素會保證被初始化為0;如果你是為指標類函數分配記憶體,那麼這些元素都會被初始化為空白指標。

(3)malloc向系統申請size個位元組的空間,申請完之後返回的是這個空間的首地址,類型為void*,而void*表示未確定的類型,在c/c++中void*可以被強轉成任意類型的指標。

(4)realloc可以對給定的指標所指向的空間進行擴大或者縮小,無論是擴大還是縮小,原有記憶體中的內容將保持不變(如果對於縮小之後的空間,被縮小的那部分空間內的資料還是會丟失)。realloc並不保證調整後的記憶體空間和原來的記憶體空間保持同一個地址。相反,realloc指標很可能指向一個新的地址。

(5)realloc是從堆上分配空間的,但當你進行擴大的時候,realloc會試圖從堆上現存的資料後面的那些位元組中擷取附加的位元組,如果能滿足,就剛好。但如果後面的位元組數不夠,其就會使用堆上第一個有足夠大小的自由塊,然後將現存的資料拷貝到新的位置,將老塊放回到堆上。在這個過程中,資料會被移動。也就是說,當你使用realloc的時候,資料可能被移動。

 

三、有關malloc的一些擴充(選自《高品質c/c++編程指南(林銳)》)

malloc 

malloc的原型:(void*)malloc(int size)(int也可以是unsigned,int只是其中的一種特例)

  malloc函數的傳回值是一個void類型的指標,參數為int類型資料,即申請分配的記憶體大小,單位是byte。記憶體配置成功之後,malloc函數返回這塊記憶體的首地址。你需要一個指標來接受這個地址。但是由於函數的傳回值是void*類型,所以必須強制轉換成你所接收的類型。也就是說,這塊記憶體將來要儲存什麼類型的資料。比如:

char* p = (char*)malloc(100);

在堆上面分配了100個位元組記憶體,返回這塊記憶體的首地址,把地址強制轉換成char*類型後賦給char*類型 的指標變數p。同時告訴我們這塊記憶體將來用來儲存char*類型的資料。也就是說你只能通過指標變數p來操作這塊記憶體。這塊記憶體本身並沒有名字,對它的訪問是匿名訪問。

 

記憶體釋放

  有分配就一定有釋放。malloc對應的就是free函數。free函數只有一個參數,就是要釋放的記憶體塊的首地址。比如:free(p);

free函數做的事情:斬斷指標變數與這塊記憶體的關係。就像上面的例子一樣malloc函數開闢的這一個資料區塊空間是屬於p的,你只能通過p來訪問這一塊資料區塊空間,而free函數做的事情就是斬斷malloc和p之間的聯絡。但是p指標本身存放的地址並沒有發生變化,只是它對指標所指向的那塊記憶體已經沒有所有權了,不能對記憶體塊進行操作。而那塊記憶體塊裡面的資料也沒有被改變,只是你沒有辦法去訪問或者修改那塊資料快中的內容了。

  malloc和free是一一對應的,如果malloc兩次但是只free一次就會存在記憶體流失,如果malloc一次但是free了兩次,就會出錯(第一次使用free的時候,malloc所開闢的空間就已經被釋放,第二次使用free就無記憶體空間可以釋放了,這種對記憶體的誤操作就有可能會導致程式的崩潰)。

  

  函數的記憶體釋放完後,一定要把p指標置為NULL。為什嗎?

  從上面可以看出,free掉之後p只是切斷了和記憶體空間的關係,但是p指標本身內部依舊存在一個地址,如果不把它置成空,那這個指標就會變成一個野指標(懸垂指標),遲早會出事。

例子:
1 char* p = (char*)malloc(100);2 strcpy(p, "hello");3 free(p);//可以看到這邊已經釋放了p所指向的那一塊空間,但是p本身儲存的地址並沒有改變4 if(NULL != p)//判斷不起作用,起不到防護作用5 {6      strcpy(p, "world");//p沒有分配空間,出錯。7 }

 

四、new/delete

  前頭講了很多但好像還沒有講到c++的動態記憶體這方面。下面我們來進行一些討論。

  我們知道c++是相容c的,那我們明明已經有了malloc和free來進行動態內容的管理,為什麼c++還要定義new和delete運算子來動態管理記憶體。

  來看一下它們之間的區別和聯絡:

  1.它們都是動態管理記憶體的入口。

  2.malloc/free是c/c++標準庫的函數,new/delete是c++操作符。

  3.malloc/free只是動態分配/釋放記憶體空間。而new/delete出來分配空間還會調用建構函式和解構函式進行初始化與清理。

  4.malloc/free需要手動計算類型大小且會返回void*, new/delete可以自己計算類型的大小,返回對應類型的指標。

  我們在c++中是允許進行重載的,那我們也可以重載一下new和delete,我在這就不做了(其實new和delete是不能重載的,即使你進行了重載,也只是重載了operator new和operator delete)。

  

有關operator new/operator delete    operator new[]/operator delete[]

總結:

  1.operator new/operator delete    operator new[]/operator delete[]的用法和malloc/free一樣。

  2.它們只負責分配空間/釋放空間,不會調用物件建構函數和解構函式來初始化/清理對象。

  3.實際operator new/operator delete  只是malloc和free的一層封裝。

 

五、new和delete在記憶體中所做的事

new做的事:1.調用operator new分配空間2.調用建構函式初始化空間 delete做的事:1.調用解構函式清理對象2.調用operator delete釋放空間 new[N]做的事:1.調用operator new分配空間2.調用N次建構函式分別初始化每個對象 delete做的事:1.調用N次解構函式清理對象2.調用operator delete釋放空間 用一張圖來解釋:

c++動態記憶體管理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.