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

Shuffy

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

第三章.        資源管理

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

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

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


 

第13條:     要使用對象來管理資源

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

class Investment { ... };          // 投資類型層次結構的基類

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

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

                                   // 層次結構中動態分配的對象,

                                   // 調用者必須要將其刪除

                                   // (為簡化代碼省略了參數表)

從上面代碼中的注釋中可以看出,當 createInvestment 的調用者完成對于 createInvestment 函數返回對象的操作后,這類調用者應負責刪除這一對象。請看下邊的代碼,我們用 f 函數來承擔這一責任:

void f()

{

 Investment *pInv = createInvestment();      // 調用工廠函數

 ...                                         // 使用 pInv

 delete pInv;                                // 釋放該對象

}

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

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

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

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

void f()

{

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

                                   // 調用工廠函數

 

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

 

}                                  // 通過 auto_ptr 的析構函數

                                   // 自動刪除 pInv

這一簡單的示例向我們展示了使用對象管理資源的兩大關鍵問題:

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

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

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

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

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

 

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

                                   // 現在 pInv2 指向這一對象,

                                   // pInv1 被重設為 null

 

pInv1 = pInv2;                     // 現在 pInv1 指向這一對象

                                   // pInv2 被重設為 null

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

引用計數智能指針( reference-counting smart pointer , 簡稱 RCSP )是 auto_ptr 的一個替代品。一個 RCSP 是一個這樣的智能指針:它可以跟蹤有多少的對象指向了一個特定的 資源,同時當沒有指針在指向這一資源時,智能指針會自動刪除這一資源??梢钥闯?, RCSP 的行為與垃圾回收機很相似。然而, RCSP 與垃圾回收機也不是完全一樣的,它不能夠打斷循環引用(比如說,兩個沒有其它使用者的對象 互相指向對方)。

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

void f()

{

 ...

 std::TR1::shared_ptr<Investment>

    pInv(createInvestment());       // 調用工廠函數

 

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

 

}                                  // 通過 shared_ptr 的析構函數

                                   // 自動刪除 pInv

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

void f()

{

   ...

 

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

                                    // pInv1 指向 createInvestment

                                      // 所返回的對象

 

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

                                    // 現在 pInv1 pInv2 均指向

                                    // 同一對象

 

 pInv1 = pInv2;                     // 同上 因為什么都沒有改變

 ...

}                                   // pInv1 pInv2 被銷毀,

                                    // 它們所指向的對象也自動被刪除了

由于復制 TR1::shared_ptr 的工作可以“如期進 ,所以在 auto_ptr 會出現非正統的復制行為的地方,比如 STL 器以及其它一些上下文中,這類指針能夠安全地應用。

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

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

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

                                   // 壞主意!

                                   // 這里將使用錯誤的刪除格式

 

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

你可能會很吃驚,因為在 C++ 中沒有類似于 auto_ptr TR1::shared_ptr 的方案來解決動態分配數組的問題,甚至 TR1 中也沒有。這是因為 vector string 通常都可以代替動態分配的數組。如果你仍然希望存在類似于 auto_ptr TR1::shared_ptr 的數組類,請參見 Boost 的相關內容(見 55 )。那兒會滿足你需求: Boost 提供了 boost::scoped_array boost::shared_array 來處理相關問題。

本條目中建議你始終使用對象來管理資源。如果你手動釋放資源(比如使用 delete 而不是使用資源管理類),你就在做一些錯事。諸如 auto_ptr TR1::shared_ptr 等封裝好的資源管理類通??梢宰屪裱緱l目的建議變成一件很容易的事情,但是某些情況下,你的問題無法使用這些預制的類來解決,此時你便需要創建自己的資源管理類。但這并沒有想象中那么難,但是確實需要你考慮一些細節問題。這些細節問題就是第 14 15 條的主題。

最后說一下,我必須指出 createInvestment 的裸指針返回類型存在著潛在的內存泄露問題,因為調用者十分容易忘記在返回時調用 delete 。(甚至在它們使用 auto_ptr TR1::shared_ptr 來運行 delete 時,他們仍然需要在一個智能指針對象中保存 createInvestment 的返回值。)解決這一問題需要改變 createInvestment 的對象,這是第 18 條的主題。

牢記在心

為了避免資源泄露,可以使用 RAII 對象,使用構造函數獲取資源,析構函數釋放資源。

auto_ptr TR1::shared_ptr 兩個常用并且實用的 RAII 類。通常情況 TR1::shared_ptr 是更好的選擇,因為它的復制行為更加直觀。復制一個 auto_ptr 將會使其重設為 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>
            久久香蕉国产线看观看av| 亚洲欧美文学| 欧美日本精品一区二区三区| 美女视频黄 久久| 一本综合久久| 女仆av观看一区| 永久555www成人免费| 亚洲国产精品精华液2区45| 亚洲福利一区| 久久精品国产成人| 国产日韩欧美自拍| 欧美一区二区福利在线| 一本一道久久综合狠狠老精东影业| 美日韩精品免费| 欧美视频专区一二在线观看| 国产精品一区视频| 99re8这里有精品热视频免费| 亚洲综合第一| 亚洲欧洲一区| 久久国产精品久久久久久| 欧美成人一区二区三区在线观看 | 亚洲嫩草精品久久| 欧美大片免费久久精品三p | 国产精品一区二区在线观看网站 | 国产麻豆成人精品| 亚洲欧洲在线观看| 欧美一区二区三区免费在线看| 免费在线看成人av| 欧美日韩视频一区二区| 亚洲美女视频| 一区二区三区久久| 亚洲欧美福利一区二区| 国产精品99久久久久久久久| 久久久蜜臀国产一区二区| 亚洲毛片av| 欧美一级免费视频| 在线观看亚洲| 国产精品视频成人| 亚洲精品视频免费观看| 国产精品亚洲产品| 国产精品视频观看| 99精品视频免费观看| 欧美一区二区免费观在线| 国产一区二区久久精品| 久久精视频免费在线久久完整在线看| 日韩一区二区久久| 99国产精品视频免费观看一公开| 国产精品美女主播| 久久综合久久综合久久综合| 欧美亚洲一区二区在线观看| 亚洲一区二区在线免费观看视频| 99国内精品久久| 欧美一区1区三区3区公司| 日韩一区二区免费高清| 欧美日韩一区成人| 午夜免费久久久久| 欧美一区二区视频在线观看2020 | 久久精品综合一区| 韩国av一区二区三区| 亚洲国产婷婷综合在线精品 | 欧美激情在线狂野欧美精品| 久久综合久久88| 亚洲欧美日韩国产成人| 久久亚洲私人国产精品va| 亚洲精品免费观看| 久久精品综合| 欧美在线免费观看亚洲| 欧美久色视频| 亚洲国产精品日韩| 伊人成人在线| 欧美一区二区三区男人的天堂| 亚洲人成高清| 久久免费视频网| 久久久国产精品一区二区中文| 欧美ed2k| 亚洲国内自拍| 亚洲视屏在线播放| 欧美日韩在线播| 亚洲美女在线一区| 亚洲午夜在线观看视频在线| 美女亚洲精品| 亚洲电影在线看| 一本一道久久综合狠狠老精东影业| 欧美一区深夜视频| 久久夜色精品国产欧美乱极品| 欧美国产精品v| 狠狠久久五月精品中文字幕| 亚洲欧美日韩国产成人| 久久精品国产欧美亚洲人人爽| 国产日韩精品一区二区三区在线| 亚洲欧美日本国产专区一区| 欧美亚洲专区| 亚洲国产精品99久久久久久久久| 久久久99国产精品免费| 美女视频一区免费观看| 亚洲精品视频免费在线观看| 欧美性久久久| 欧美电影免费观看大全| 一区二区激情| 亚洲第一福利视频| 久久er精品视频| 中文国产亚洲喷潮| 亚洲二区视频| 国产在线观看一区| 国产精品久久久久秋霞鲁丝| 久久蜜桃资源一区二区老牛| 一本色道久久综合亚洲精品按摩 | 亚洲免费影视| 亚洲人成人一区二区三区| 国产精品天天看| 欧美视频在线观看 亚洲欧| 久久久欧美精品| 久久精品一区二区三区四区| 国产日韩欧美亚洲一区| 久久久久网址| 亚洲综合电影一区二区三区| 亚洲精品系列| 99日韩精品| 99视频在线精品国自产拍免费观看 | 国产精品丝袜91| 欧美日韩国产首页| 国产精品久久久久久超碰| 国产欧美视频一区二区| 国产精品久久久一区麻豆最新章节 | 日韩亚洲欧美中文三级| 狠狠色狠狠色综合日日tαg| 伊人久久婷婷色综合98网| 在线精品视频在线观看高清| 在线精品观看| 亚洲一区二区四区| 久久久之久亚州精品露出| 亚洲黄色三级| 亚洲欧美另类中文字幕| 久久成人免费日本黄色| 免费日韩av电影| 国产欧美短视频| 亚洲精品日韩综合观看成人91| 亚洲欧美日韩视频二区| 女女同性精品视频| 亚洲欧美日韩一区二区三区在线观看| 久久精品系列| 国产精品三区www17con| 亚洲美女一区| 亚洲成色999久久网站| 性做久久久久久免费观看欧美| 久久久久免费| 国产一区二区三区久久| 午夜视黄欧洲亚洲| 亚洲国产小视频| 久久久www免费人成黑人精品 | 亚洲综合首页| 欧美日韩精品免费在线观看视频| 黄色资源网久久资源365| 久久精品中文| 久久米奇亚洲| 亚洲人成网站色ww在线 | 欧美在线播放| 国产揄拍国内精品对白| 久久精品人人做人人爽电影蜜月| 一区二区三区波多野结衣在线观看| 女女同性精品视频| 一区二区三区欧美激情| 亚洲最新在线| 国产一区二区高清视频| 另类图片综合电影| 女主播福利一区| 亚洲在线观看视频| 久久久久在线| 亚洲一区二区三区四区中文 | 亚洲日本欧美日韩高观看| 欧美电影在线观看| 欧美一区二区国产| 欧美mv日韩mv国产网站| 午夜精品在线| 欧美日韩国语| 欧美激情中文字幕在线| 国产精品女主播| 欧美激情精品久久久久久| 国产女主播一区二区| 欧美一级免费视频| 欧美一区二区黄色| 亚洲国产精品免费| 在线视频你懂得一区| 久久国产精品高清| 久久麻豆一区二区| 亚洲成在人线av| 久久久久五月天| 榴莲视频成人在线观看| 亚洲精品在线二区| 国产视频一区欧美| 欧美激情五月| 久久久国产一区二区| 一区二区欧美视频| 免费久久99精品国产自| 午夜精品久久久久久久男人的天堂| 在线日韩av永久免费观看| 欧美日韩在线视频首页| 欧美尤物巨大精品爽| 一本一本久久a久久精品综合麻豆| 久久激情久久|