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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

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

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

??? 在C語(yǔ)言庫(kù)中,提供了這么兩個(gè)函數(shù),malloc和free,分別用于執(zhí)行動(dòng)態(tài)內(nèi)存分配和釋放。兩個(gè)函數(shù)的聲明如下:

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

??? 從外觀上看,malloc函數(shù)的參數(shù)是接受需要分配的內(nèi)存字節(jié)數(shù),如果內(nèi)存能夠滿足請(qǐng)求量,那么將會(huì)返回:指向被分配的內(nèi)存塊起始位置的指針(引用自《C和指針》中的表述)。而且,這塊內(nèi)存是一塊連續(xù)的內(nèi)存。夠爽吧!如果分配不成功的話,那么就返回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的空間,返回了相應(yīng)的指針 ? if (!newnode) // 為了防止空指針的存在,要檢查是否分配成功 { printf("內(nèi)存分配不成功!\n"); exit(1); }

??? 在這里,我們又一次看到了void指針的功效。對(duì)于不同類型的指針轉(zhuǎn)換,void指針都能應(yīng)付自如,更重要的是,我們不用為每種類型都特化一個(gè)內(nèi)存分配版本。這個(gè)會(huì)累死的。還有,對(duì)于分配出來(lái)的指針,我們要檢查它是否為空,這是為什嗎?因?yàn)?#xff0c;對(duì)于空指針的操作將會(huì)帶來(lái)未知的錯(cuò)誤,所以錯(cuò)誤摁在萌芽階段是我們的義務(wù)和責(zé)任。

??? 內(nèi)存的東西,向來(lái)都是要有借有還。有malloc就會(huì)有free。free函數(shù)的作用就是負(fù)責(zé)釋放申請(qǐng)來(lái)的內(nèi)存的。這個(gè)指向釋放的內(nèi)存指針是有講究的,你不能釋放申請(qǐng)來(lái)的一小部分的區(qū)域。例如:

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

??? 其次,較為常見(jiàn)失誤在于,我們對(duì)申請(qǐng)的內(nèi)存指針進(jìn)行操作,操作完之后,對(duì)其進(jìn)行釋放。此時(shí),釋放不成功的原理和上面這個(gè)例子一樣,釋放了部分的內(nèi)存,而不是釋放全部?jī)?nèi)存。一般的做法是設(shè)一個(gè)臨時(shí)變量保存malloc來(lái)的指針,在釋放的時(shí)候,就釋放這個(gè)指針?biāo)缘膬?nèi)存區(qū)域,這樣就不會(huì)出錯(cuò)了。

??? 關(guān)于內(nèi)存越界,這是一個(gè)很普遍的問(wèn)題。這個(gè)只能你去親自把握,記清楚你申請(qǐng)了多少,其邊界在哪里,不要出錯(cuò)就埋怨電腦。

??? 說(shuō)了malloc和free,那就進(jìn)入今天的主題new和delete了。

??? 想必我們都寫(xiě)過(guò)這樣的代碼吧。

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

??? 我們都知道new在堆上創(chuàng)建了一個(gè)string類型對(duì)象,這個(gè)看似一個(gè)動(dòng)作的事情卻暗地包含了三件事:獲得一塊內(nèi)存空間、調(diào)用構(gòu)造函數(shù)、返回正確的指針。相當(dāng)于下面:

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

??? 你應(yīng)該會(huì)心里犯嘀咕,臥槽,怎么出現(xiàn)了這么多的環(huán)節(jié)。其實(shí)呢,new可分為這么三種情形:new operator(我們平常用的new), operator new(用來(lái)分配內(nèi)存的),placement new(構(gòu)造對(duì)象的)。當(dāng)然,你要用placement new的時(shí)候,你要加入<new>的頭函數(shù)。

??? ⑴ new operator

??? new operator的第一步分配內(nèi)存實(shí)際上是通過(guò)調(diào)用operator new來(lái)完成的,這里的new是可以重載的。operator new默認(rèn)情況下首先調(diào)用分配內(nèi)存的代碼,嘗試得到一段堆上的空間,如果成功就返回,如果失敗,則轉(zhuǎn)而去調(diào)用一個(gè)new_hander,然后繼續(xù)重復(fù)前面過(guò)程。

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

??? 運(yùn)行的結(jié)果如下:

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

⑵ placement new

??? placement new的作用是用來(lái)實(shí)現(xiàn)定位構(gòu)造對(duì)象,可以說(shuō)相當(dāng)于new operator三步操作中的第二步,也就是在取得了一塊可以容納指定類型對(duì)象的內(nèi)存后,在這塊內(nèi)存上構(gòu)造一個(gè)對(duì)象。其用法:

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

??? 其格式是這樣的:new(指針指向的內(nèi)存地址) 類型(值)。對(duì)照格式,可以這么說(shuō)是在__p上構(gòu)造一個(gè)_Tp類型的,值為_(kāi)_val。

??? 如果是像上面那樣在棧上使用了placement new,則必須手工調(diào)用析構(gòu)函數(shù):

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

??? 當(dāng)覺(jué)得默認(rèn)的new operator對(duì)內(nèi)存的管理不能滿足我們的需求,我們可以自己手工打造內(nèi)存管理,此時(shí)的placement new就相當(dāng)有用了。以上兩段代碼源于sgi stl的alloc中,就說(shuō)明問(wèn)題了。

⑶ new operator 和 operator new 的取舍

??? 兩個(gè)關(guān)鍵詞很容易讓人迷糊,兩者又都是骨肉相連的狀態(tài),取舍有點(diǎn)不易。對(duì)于取舍的評(píng)判,我挪用了《more effective C++》中的觀點(diǎn):“如果你想產(chǎn)生對(duì)象在heap上,那么就用new operator,它不但分配內(nèi)存,而且為該對(duì)象調(diào)用了構(gòu)造函數(shù);如果你只打算分配內(nèi)存,那么就用operator new ,只分配內(nèi)存,其余的事情都沒(méi)做。當(dāng)然,使用operator new 后續(xù)的對(duì)象構(gòu)造也要跟上,不然但分配內(nèi)存也就沒(méi)有意義了。”

??? 總結(jié),在這篇文章中,介紹了malloc,free,new,delete的使用和一些心得體會(huì)。當(dāng)然,還有許多的內(nèi)容沒(méi)有做相應(yīng)的介紹,比如new_handle等內(nèi)容。抱歉,抱歉!

??? 關(guān)于內(nèi)存分配的問(wèn)題,你還可以參考:內(nèi)存分配機(jī)制。這篇文章介紹了C/C++內(nèi)存分配的知識(shí)。

參考文獻(xiàn)

1. 《C語(yǔ)言程序設(shè)計(jì)》

2. 《C和指針》

3. 《C專家編程》

4. 《more effective C++》

5. 《STL源碼解析》

轉(zhuǎn)載于:https://www.cnblogs.com/ComputerG/archive/2012/03/10/2389328.html

總結(jié)

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

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。