青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Shuffy

不斷的學(xué)習(xí),不斷的思考,才能不斷的進(jìn)步.Let's do better together!
posts - 102, comments - 43, trackbacks - 0, articles - 19
[轉(zhuǎn)]http://m.shnenglu.com/tiandejian/archive/2007/05/07/ECPP_13.html

第三章.        資源管理

資源是這樣一種東西:一旦你借助它們所做的事情完成了,你必須要將其返回給系統(tǒng)。如果你沒有這樣做,那么不好的事情就會(huì)發(fā)生。在 C++ 程序中,最常用的資源是動(dòng)態(tài)分配的內(nèi)存(如果你分配了內(nèi)存但是卻忘記了釋放它們,你的程序就會(huì)遇到一次內(nèi)存泄漏),但是內(nèi)存只是你所需要管理的眾多資源中的一種。其它常見的資源包括文件主字碼、互斥鎖、以及圖形用戶界面( GUI )中的字體和畫筆、數(shù)據(jù)庫聯(lián)接、網(wǎng)絡(luò)套結(jié)字。無論是何種資源,在你借助它所做的工作完成以后都要將其釋放,這一點(diǎn)是很重要的。

試圖手動(dòng)將資源管理得井井有條,在任何情況下都是很困難的事情。但當(dāng)問題轉(zhuǎn)向異常處理、多路返回函數(shù)、以及當(dāng)維護(hù)程序員在未對(duì)其所作的修改有充分理解之前就輕舉妄動(dòng)時(shí),你就會(huì)清楚地發(fā)現(xiàn),專門用來解決資源管理問題的方法并不是很充足。

本章以介紹一個(gè)基于對(duì)象的資源管理方法開始,該方法構(gòu)建于 C++ 所支持的構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝操作符之上。實(shí)踐顯示,如果嚴(yán)格時(shí)刻堅(jiān)持這一方法,便可以消滅資源管理中幾乎全部的潛在問題。本章稍靠后一些的條目中將專門講解內(nèi)存管理的問題。這些條目是對(duì)前邊較為一般化的條目的補(bǔ)充,因?yàn)楣芾韮?nèi)存的對(duì)象需要搞清楚如何正常工作。


 

第13條:     要使用對(duì)象來管理資源

在下面的示例中,我們的工作將圍繞一個(gè)模擬投資(或者是股票、證券等等,均可)的庫展開,在這個(gè)庫中,各種各樣的投資類型都繼承自同一個(gè)基類—— Investment

class Investment { ... };          // 投資類型層次結(jié)構(gòu)的基類

我們繼續(xù)上面的示例,供我們使用的庫中,為我們提供具體 Investment 對(duì)象是通過工廠函數(shù)(參見第 7 條)來實(shí)現(xiàn)的:

Investment* createInvestment();    // 返回一個(gè)指針,指向 Investment

                                   // 層次結(jié)構(gòu)中動(dòng)態(tài)分配的對(duì)象,

                                   // 調(diào)用者必須要將其刪除

                                   // (為簡(jiǎn)化代碼省略了參數(shù)表)

從上面代碼中的注釋中可以看出,當(dāng) createInvestment 的調(diào)用者完成對(duì)于 createInvestment 函數(shù)返回對(duì)象的操作后,這類調(diào)用者應(yīng)負(fù)責(zé)刪除這一對(duì)象。請(qǐng)看下邊的代碼,我們用 f 函數(shù)來承擔(dān)這一責(zé)任:

void f()

{

 Investment *pInv = createInvestment();      // 調(diào)用工廠函數(shù)

 ...                                         // 使用 pInv

 delete pInv;                                // 釋放該對(duì)象

}

這看上去可以正常運(yùn)行,但是 f 可能在一些情況下無法成功的刪除來自 createInvestment 的對(duì)象。在上述代碼的“ ... ”部分可能存在不成熟的 return 語句。如果這樣的 return 語句得到了執(zhí)行,那么程序永遠(yuǎn)就不會(huì)轉(zhuǎn)向 delete 語句執(zhí)行。當(dāng)在循環(huán)語句中使用 createInvestment delete 時(shí),會(huì)出現(xiàn)類似的情形,同時(shí)這樣的循環(huán)也有可能因遇到 continue goto 語句而提前退出。最后,“ ... ”中的一些語句還有可能拋出異常。如果真的有異常拋出,程序同樣也不會(huì)達(dá)到 delete 。無論 delete 是如何被跳過的,包含 Investment 對(duì)象的內(nèi)存都有可能泄露,同時(shí)這類對(duì)象所控制的資源都有可能得不到釋放。

當(dāng)然,用心編程就有可能防止這類錯(cuò)誤發(fā)生,但是請(qǐng)想象一下代碼會(huì)多么的不固定——你需要不停地修改代碼。在軟件維護(hù)的過程中,為一個(gè)函數(shù)添加 return continue 語句可能會(huì)對(duì)其資源管理策略造成怎樣的影響呢,一些人可能由于不完全理解這一問題就這樣做了。還有更嚴(yán)重的,就是 f 函數(shù)的“ ... ”部分可能調(diào)用了一個(gè)這樣的函數(shù):它原先從不會(huì)拋出異常,但在其得到“改進(jìn)”之后,它突然又開始能夠拋出異常了。寄希望于 f 函數(shù)總能達(dá)到其中的 delete 語句并不可靠。

為了確保 createInvestment 所返回的資源總能得到釋放,我們需要將這類資源放置在一個(gè)對(duì)象中,這一對(duì)象的析構(gòu)函數(shù)應(yīng)在程序離開 f 之后自動(dòng)釋放資源。實(shí)際上,這是本條目所蘊(yùn)含的思想的一半:那就是將資源放置在對(duì)象中,我們可以寄希望于通過調(diào)用 C++ 的默認(rèn)析構(gòu)函數(shù),從而確保資及時(shí)源得到釋放。

許多資源是在堆上動(dòng)態(tài)分配的,并且僅僅在單一的程序塊或函數(shù)中使用,同時(shí)這類資源應(yīng)該在程序離開這一程序塊或函數(shù)之前得到釋放。標(biāo)準(zhǔn)庫中的 auto_ptr 就是為這類情況量身定做的。 auto_ptr 是一個(gè)類似于指針的對(duì)象(一個(gè)智能指針),其析構(gòu)函數(shù)可以自動(dòng)地對(duì)用其所指的內(nèi)容執(zhí)行 delete 。以下的代碼描述了如何使用 auto_ptr 來防止 f 潛在的資源泄露。

void f()

{

 std::auto_ptr<Investment> pInv(createInvestment());

                                   // 調(diào)用工廠函數(shù)

 

 ...                              // pInv 的用法和原來相同

 

}                                  // 通過 auto_ptr 的析構(gòu)函數(shù)

                                   // 自動(dòng)刪除 pInv

這一簡(jiǎn)單的示例向我們展示了使用對(duì)象管理資源的兩大關(guān)鍵問題:

獲取資源后,立即將資源轉(zhuǎn)交給資源管理對(duì)象。 上邊的示例中 createInvestment 返回的資源將初始化一個(gè) auto_ptr ,從而實(shí)現(xiàn)對(duì)這類資源的管理。事實(shí)上,使用對(duì)象來管理資源的理念通常稱為“資源獲取即初始化”( Resource Acquisition Is Initialization 簡(jiǎn)稱 RAII ),這是因?yàn)樵谕粋€(gè)語句中獲取一個(gè)資源并且初始化一個(gè)資源管理對(duì)象是很平常的。某些時(shí)候獲取資源就是為一個(gè)資源管理對(duì)象賦值,而不是初始化。但是無論是哪種途徑,在獲取資源時(shí),每一個(gè)資源都都會(huì)立即轉(zhuǎn)向一個(gè)資源管理對(duì)象。

資源管理對(duì)象使用其析構(gòu)函數(shù)來確保資源得到釋放。 由于析構(gòu)函數(shù)是在對(duì)象銷毀時(shí)自動(dòng)調(diào)用的(比如,當(dāng)對(duì)象將到達(dá)其作用域之外),所以不管程序是如何離開一個(gè)塊的,資源都會(huì)被正確地釋放。如果釋放資源會(huì)帶來異常,那么事情就會(huì)變得錯(cuò)綜復(fù)雜。但是那第 8 條中介紹的內(nèi)容,我們這里不關(guān)心這些。

由于當(dāng)一個(gè) auto_ptr 被銷毀時(shí),它 自動(dòng)刪除了其所指向的內(nèi)容,所以永遠(yuǎn)不要讓多個(gè) auto_ptr 指向同一個(gè)對(duì)象,這一點(diǎn)很重要。如果你這樣做了,這個(gè)對(duì)象就會(huì)被多次刪除,這樣你的程序就會(huì)陷入未知行為的陷阱。為了防止此類問題發(fā)生, auto_ptr 有一個(gè)不同尋常的特性:如果你復(fù)制它們(通過拷貝構(gòu)造函數(shù)或者拷貝賦值運(yùn)算符),它們就會(huì)被重設(shè)為 null ,然后資源的所有權(quán)將由復(fù)制出的指針獨(dú)占!

std::auto_ptr<Investment>          // pInv1 指向 createInvestment

 pInv1(createInvestment());        // 所返回的對(duì)象

 

std::auto_ptr<Investment> pInv2(pInv1);

                                   // 現(xiàn)在 pInv2 指向這一對(duì)象,

                                   // pInv1 被重設(shè)為 null

 

pInv1 = pInv2;                     // 現(xiàn)在 pInv1 指向這一對(duì)象

                                   // pInv2 被重設(shè)為 null

在這一古怪的復(fù)制方法中,由于 auto_ptr 必須僅僅指向一個(gè)資源,因此增加了對(duì)于資源管理的潛在需求。這意味著 auto_ptr 并不適合于所有動(dòng)態(tài)分配的資源。比如說, STL 容器要求其內(nèi)容的表現(xiàn)出“正常”的拷貝行為,所以 auto_ptr 的容器是不允許使用的。

引用計(jì)數(shù)智能指針( reference-counting smart pointer 簡(jiǎn)稱 RCSP )是 auto_ptr 的一個(gè)替代品。一個(gè) RCSP 是一個(gè)這樣的智能指針:它可以跟蹤有多少的對(duì)象指向了一個(gè)特定的 資源,同時(shí)當(dāng)沒有指針在指向這一資源時(shí),智能指針會(huì)自動(dòng)刪除這一資源。可以看出, RCSP 的行為與垃圾回收機(jī)很相似。然而, RCSP 與垃圾回收機(jī)也不是完全一樣的,它不能夠打斷循環(huán)引用(比如說,兩個(gè)沒有其它使用者的對(duì)象 互相指向?qū)Ψ剑?/span>

TR1 TR1::shared_ptr 就是一個(gè) RCSP 于是你可以按下面的方式來編寫 f

void f()

{

 ...

 std::TR1::shared_ptr<Investment>

    pInv(createInvestment());       // 調(diào)用工廠函數(shù)

 

 ...                              // pInv 的用法與前面相同

 

}                                  // 通過 shared_ptr 的析構(gòu)函數(shù)

                                   // 自動(dòng)刪除 pInv

上面的代碼與使用 auto_ptr 是幾乎完全相同,但是復(fù)制 shared_ptr 的行為更加自然:

void f()

{

   ...

 

 std::TR1::shared_ptr<Investment> pInv1(createInvestment());

                                    // pInv1 指向 createInvestment

                                      // 所返回的對(duì)象

 

 std::TR1::shared_ptr<Investment> pInv2(pInv1);

                                    // 現(xiàn)在 pInv1 pInv2 均指向

                                    // 同一對(duì)象

 

 pInv1 = pInv2;                     // 同上 因?yàn)槭裁炊紱]有改變

 ...

}                                   // pInv1 pInv2 被銷毀,

                                    // 它們所指向的對(duì)象也自動(dòng)被刪除了

由于復(fù)制 TR1::shared_ptr 的工作可以“如期進(jìn) ,所以在 auto_ptr 會(huì)出現(xiàn)非正統(tǒng)的復(fù)制行為的地方,比如 STL 器以及其它一些上下文中,這類指針能夠安全地應(yīng)用。

但是,請(qǐng)不要迷失方向。本條目并不是專門講解 auto_ptr TR1::shared_ptr 的,也不是講解智能指針的。本條目的核心內(nèi)容是使用對(duì)象管理資源的重要性。 auto_ptr TR1::shared_ptr 僅僅是這類對(duì)象的示例。(關(guān)于 TR1::shared_ptr 的更多信息,請(qǐng)參見第 14 18 54 條。)

auto_ptr TR1::shared_ptr 在析構(gòu)函數(shù)中都包含 delete 語句,而不是 delete[] 。(第 16 條中描述了二者的區(qū)別。)這就意味著對(duì)于動(dòng)態(tài)分配的數(shù)組使用 auto_ptr TR1::shared_ptr 不是一個(gè)好主意。但是遺憾的是,這樣的代碼會(huì)通過編譯:

std::auto_ptr <std::string> aps(new std::string[10]);

                                   // 壞主意!

                                   // 這里將使用錯(cuò)誤的刪除格式

 

std::TR1::shared_ptr <int> spi(new int[1024]);    // 同樣的問題

你可能會(huì)很吃驚,因?yàn)樵?/span> C++ 中沒有類似于 auto_ptr TR1::shared_ptr 的方案來解決動(dòng)態(tài)分配數(shù)組的問題,甚至 TR1 中也沒有。這是因?yàn)?/span> vector string 通常都可以代替動(dòng)態(tài)分配的數(shù)組。如果你仍然希望存在類似于 auto_ptr TR1::shared_ptr 的數(shù)組類,請(qǐng)參見 Boost 的相關(guān)內(nèi)容(見 55 )。那兒會(huì)滿足你需求: Boost 提供了 boost::scoped_array boost::shared_array 來處理相關(guān)問題。

本條目中建議你始終使用對(duì)象來管理資源。如果你手動(dòng)釋放資源(比如使用 delete 而不是使用資源管理類),你就在做一些錯(cuò)事。諸如 auto_ptr TR1::shared_ptr 等封裝好的資源管理類通常可以讓遵循本條目的建議變成一件很容易的事情,但是某些情況下,你的問題無法使用這些預(yù)制的類來解決,此時(shí)你便需要?jiǎng)?chuàng)建自己的資源管理類。但這并沒有想象中那么難,但是確實(shí)需要你考慮一些細(xì)節(jié)問題。這些細(xì)節(jié)問題就是第 14 15 條的主題。

最后說一下,我必須指出 createInvestment 的裸指針返回類型存在著潛在的內(nèi)存泄露問題,因?yàn)檎{(diào)用者十分容易忘記在返回時(shí)調(diào)用 delete 。(甚至在它們使用 auto_ptr TR1::shared_ptr 來運(yùn)行 delete 時(shí),他們?nèi)匀恍枰谝粋€(gè)智能指針對(duì)象中保存 createInvestment 的返回值。)解決這一問題需要改變 createInvestment 的對(duì)象,這是第 18 條的主題。

牢記在心

為了避免資源泄露,可以使用 RAII 對(duì)象,使用構(gòu)造函數(shù)獲取資源,析構(gòu)函數(shù)釋放資源。

auto_ptr TR1::shared_ptr 兩個(gè)常用并且實(shí)用的 RAII 類。通常情況 TR1::shared_ptr 是更好的選擇,因?yàn)樗膹?fù)制行為更加直觀。復(fù)制一個(gè) auto_ptr 將會(huì)使其重設(shè)為 null

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲乱码国产乱码精品精天堂| 亚洲一区在线播放| 欧美一级片久久久久久久| 在线欧美影院| 欧美日韩免费在线视频| 亚洲一二三级电影| 欧美在线视频免费| 亚洲人成网站在线播| 一区二区三区免费看| 欧美日韩一区成人| 亚洲欧美国产精品专区久久| aaa亚洲精品一二三区| 亚洲国内精品在线| 亚洲黄色片网站| 欧美国产一区二区| 亚洲色图综合久久| 一区二区日韩免费看| 久久视频在线免费观看| 久久精品理论片| 在线观看国产精品网站| 久久精品电影| 亚洲每日在线| 午夜精品三级视频福利| 国产丝袜一区二区三区| 国产精品久久波多野结衣| 久久精品中文字幕免费mv| 亚洲一区日韩在线| 亚洲国产成人tv| 99精品国产在热久久婷婷| 一区二区高清视频| 欧美激情中文字幕乱码免费| 国产精品h在线观看| 亚洲国产一区二区在线| 亚洲二区在线| 午夜精品久久久久久久白皮肤 | 乱中年女人伦av一区二区| 亚洲国产欧美一区二区三区久久| 欧美日韩免费观看一区=区三区| 久久久久国产精品人| 一区二区三区精品国产| 亚洲国产精品成人久久综合一区| 亚洲天堂av在线免费| 亚洲欧美区自拍先锋| 91久久久国产精品| 久久久久网址| 久久免费视频在线观看| 亚洲理伦在线| 美女国产精品| 亚洲一区二区三区国产| 国产精品99久久久久久宅男| 欧美国产日韩在线| 日韩视频一区二区在线观看| 久久久国产午夜精品| 免费视频最近日韩| 另类尿喷潮videofree | 99国产欧美久久久精品| 欧美福利精品| 亚洲高清精品中出| 亚洲精品一区二区三区不| 国产精品黄页免费高清在线观看| 在线视频免费在线观看一区二区| 亚洲尤物精选| 国产欧美在线播放| 久久夜色精品国产欧美乱极品 | 亚洲视频一二三| 免费亚洲一区| 亚洲电影第三页| 一区二区三区不卡视频在线观看 | 欧美亚洲视频| 亚洲黄色免费电影| 国产乱码精品一区二区三区忘忧草| 欧美精品91| 国产欧美精品一区| 亚洲国产视频一区| 国产精品久久久久一区二区| 久久黄色小说| 久久久久久久久一区二区| 国产日本欧美一区二区三区在线 | 久久精品国内一区二区三区| 亚洲激情影院| 在线日韩欧美视频| 99热这里只有成人精品国产| 亚洲男女自偷自拍| 亚洲国产欧美一区二区三区同亚洲 | 国产视频丨精品|在线观看| 激情欧美一区二区三区在线观看| 亚洲六月丁香色婷婷综合久久| 亚洲欧美电影院| 亚洲国产精品久久久久秋霞影院 | 久久精品99久久香蕉国产色戒| 午夜精品久久久久久99热| 国产精品人人做人人爽人人添| 欧美三级黄美女| 老司机午夜精品视频| 欧美一区二区三区在线免费观看| 一个人看的www久久| 亚洲电影网站| 欧美在线啊v一区| 欧美成人高清| 亚洲精品久久7777| 亚洲国产精品嫩草影院| 一二三区精品福利视频| 激情91久久| 国产精品视频网| 亚洲国产精品电影| 久久久噜噜噜| 美女黄色成人网| 蜜桃av一区| 久久久爽爽爽美女图片| 亚洲网站在线播放| 亚洲午夜精品网| 樱花yy私人影院亚洲| 免费h精品视频在线播放| 一区二区三区视频在线| 麻豆国产精品777777在线| 在线精品观看| 欧美日韩免费区域视频在线观看| 麻豆成人在线| 9l国产精品久久久久麻豆| 美国成人直播| 国产精品久久久久久久久久免费| 久久久久久国产精品mv| 午夜一级在线看亚洲| 一区二区三区三区在线| 亚洲精品久久久久中文字幕欢迎你| 欧美一区二区三区喷汁尤物| 91久久综合亚洲鲁鲁五月天| 国产一区二区三区直播精品电影| 久久福利影视| 欧美激情一区二区久久久| 午夜精品美女自拍福到在线| 亚洲黄色在线看| 亚洲午夜av电影| 亚洲九九爱视频| 亚洲第一毛片| 老司机亚洲精品| 欧美xart系列高清| 亚洲国产老妈| 亚洲午夜精品久久久久久浪潮| 夜夜嗨av色综合久久久综合网| avtt综合网| 欧美国产先锋| 精品99一区二区| 亚洲欧洲一区二区天堂久久| 午夜精品久久久久久久99热浪潮| 欧美黄色小视频| 在线亚洲美日韩| 久久综合九色综合久99| 欧美三级视频在线| 一本色道久久综合亚洲精品不卡| 久久一区欧美| 久久国产视频网站| 久久精品国产999大香线蕉| 精品成人在线| 美女网站久久| 亚洲国产精品成人| 欧美一区二区三区免费观看 | 亚洲无限av看| 欧美激情一区二区三区| 亚洲精选久久| 亚洲免费观看视频| 欧美日韩大片| 亚洲免费视频在线观看| 午夜在线精品| 9l视频自拍蝌蚪9l视频成人| 久久久97精品| 欧美一区二区三区婷婷月色| 欧美成人第一页| 亚洲香蕉在线观看| 亚洲一区二区在线观看视频| 欧美黄色成人网| 日韩一区二区福利| 亚洲午夜一区二区| 欧美一区二区性| 久久久亚洲高清| 欧美精品一区在线| 久久久久久69| 久久成人在线| 欧美日韩亚洲一区在线观看| 午夜久久黄色| 亚洲视频成人| 欧美日韩一区二区三区| 亚洲综合社区| 久久精品在线视频| 欧美在线资源| 欧美激情一区二区久久久| 久久久久久夜精品精品免费| 久久久久久久波多野高潮日日 | 欧美v国产在线一区二区三区| 亚洲国产经典视频| 亚洲女优在线| 黄网动漫久久久| 欧美一区二区三区啪啪| 亚洲国产精品高清久久久| 午夜精品影院| 卡一卡二国产精品| 国产精品普通话对白| 欧美国产在线电影| 欧美制服丝袜第一页| 欧美亚洲尤物久久|