日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

malloc,free,new,delete解析(原)

發布時間:2024/9/5 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 malloc,free,new,delete解析(原) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??? 使用C/C++的苦逼娃們經常深陷內存越界錯誤,資源泄漏錯誤等等問題,而且這樣的慘劇每時每刻都在這個世界上重復的發生著。其實,我也是苦逼娃!也為了個神馬越界的東西debug了整個下午過,為此也想砸電腦過。最后想想,其實不是C/C++苦逼,是我們的不小心而造成如此的苦逼。罪過,罪過。。。

??? 在C語言庫中,提供了這么兩個函數,malloc和free,分別用于執行動態內存分配和釋放。兩個函數的聲明如下:

void* malloc(size_t size); void free(void *pointer);

??? 從外觀上看,malloc函數的參數是接受需要分配的內存字節數,如果內存能夠滿足請求量,那么將會返回:指向被分配的內存塊起始位置的指針(引用自《C和指針》中的表述)。而且,這塊內存是一塊連續的內存。夠爽吧!如果分配不成功的話,那么就返回null指針。例如:

struct Node { data_type value; struct Node *pre_node; struct Node *next_node; }; ? typedef struct Node *List; ? List newnode = NULL; ? newnode = (List)malloc(sizeof(struct Node)); // 分配了Node的空間,返回了相應的指針 ? if (!newnode) // 為了防止空指針的存在,要檢查是否分配成功 { printf("內存分配不成功!\n"); exit(1); }

??? 在這里,我們又一次看到了void指針的功效。對于不同類型的指針轉換,void指針都能應付自如,更重要的是,我們不用為每種類型都特化一個內存分配版本。這個會累死的。還有,對于分配出來的指針,我們要檢查它是否為空,這是為什嗎?因為,對于空指針的操作將會帶來未知的錯誤,所以錯誤摁在萌芽階段是我們的義務和責任。

??? 內存的東西,向來都是要有借有還。有malloc就會有free。free函數的作用就是負責釋放申請來的內存的。這個指向釋放的內存指針是有講究的,你不能釋放申請來的一小部分的區域。例如:

int *pi; ? pi = (int *)malloc(sizeof(int)*10); ? free(pi + 5); // 這里就苦逼了!

??? 其次,較為常見失誤在于,我們對申請的內存指針進行操作,操作完之后,對其進行釋放。此時,釋放不成功的原理和上面這個例子一樣,釋放了部分的內存,而不是釋放全部內存。一般的做法是設一個臨時變量保存malloc來的指針,在釋放的時候,就釋放這個指針所以的內存區域,這樣就不會出錯了。

??? 關于內存越界,這是一個很普遍的問題。這個只能你去親自把握,記清楚你申請了多少,其邊界在哪里,不要出錯就埋怨電腦。

??? 說了malloc和free,那就進入今天的主題new和delete了。

??? 想必我們都寫過這樣的代碼吧。

string *str = new string("memory alloc!");

??? 我們都知道new在堆上創建了一個string類型對象,這個看似一個動作的事情卻暗地包含了三件事:獲得一塊內存空間、調用構造函數、返回正確的指針。相當于下面:

void *pstr = operator new(sizeof(string)); new(pstr) string("memory alloc!"); string *str = static_cast<string*>(pstr);

??? 你應該會心里犯嘀咕,臥槽,怎么出現了這么多的環節。其實呢,new可分為這么三種情形:new operator(我們平常用的new), operator new(用來分配內存的),placement new(構造對象的)。當然,你要用placement new的時候,你要加入<new>的頭函數。

??? ⑴ new operator

??? new operator的第一步分配內存實際上是通過調用operator new來完成的,這里的new是可以重載的。operator new默認情況下首先調用分配內存的代碼,嘗試得到一段堆上的空間,如果成功就返回,如果失敗,則轉而去調用一個new_hander,然后繼續重復前面過程。

#include <iostream> using namespace std; ? class MyClass { private: ? public: MyClass() { }; ? void* operator new(size_t size) { cout << "調用了operator new" << endl; return ::operator new(size); } }; ? int main() { MyClass *a = new MyClass(); return 0; }

??? 運行的結果如下:

??? 相應的,delete也有delete operator和operator delete之分,后者也是可以重載的。并且,如果重載了operator new,就應該也相應的重載operator delete。

⑵ placement new

??? placement new的作用是用來實現定位構造對象,可以說相當于new operator三步操作中的第二步,也就是在取得了一塊可以容納指定類型對象的內存后,在這塊內存上構造一個對象。其用法:

void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }

??? 其格式是這樣的:new(指針指向的內存地址) 類型(值)。對照格式,可以這么說是在__p上構造一個_Tp類型的,值為__val。

??? 如果是像上面那樣在棧上使用了placement new,則必須手工調用析構函數:

void destroy(pointer __p) { __p->~_Tp(); }

??? 當覺得默認的new operator對內存的管理不能滿足我們的需求,我們可以自己手工打造內存管理,此時的placement new就相當有用了。以上兩段代碼源于sgi stl的alloc中,就說明問題了。

⑶ new operator 和 operator new 的取舍

??? 兩個關鍵詞很容易讓人迷糊,兩者又都是骨肉相連的狀態,取舍有點不易。對于取舍的評判,我挪用了《more effective C++》中的觀點:“如果你想產生對象在heap上,那么就用new operator,它不但分配內存,而且為該對象調用了構造函數;如果你只打算分配內存,那么就用operator new ,只分配內存,其余的事情都沒做。當然,使用operator new 后續的對象構造也要跟上,不然但分配內存也就沒有意義了。”

??? 總結,在這篇文章中,介紹了malloc,free,new,delete的使用和一些心得體會。當然,還有許多的內容沒有做相應的介紹,比如new_handle等內容。抱歉,抱歉!

??? 關于內存分配的問題,你還可以參考:內存分配機制。這篇文章介紹了C/C++內存分配的知識。

參考文獻

1. 《C語言程序設計》

2. 《C和指針》

3. 《C專家編程》

4. 《more effective C++》

5. 《STL源碼解析》

轉載于:https://www.cnblogs.com/ComputerG/archive/2012/03/10/2389328.html

總結

以上是生活随笔為你收集整理的malloc,free,new,delete解析(原)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。