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

洛譯小筑

別來無恙,我的老友…
隨筆 - 45, 文章 - 0, 評論 - 172, 引用 - 0
數據加載中……

[ECPP讀書筆記 條目13] 使用對象來管理資源

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

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

繼續上面的示例,我們考慮通過工廠函數(參見條目7)來提供具體的Investment對象:

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

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

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

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

從上面代碼中的注釋中可以看出,當調用者完成對于createInvestment函數返回對象的操作后,有義務刪除這一對象。請看下邊代碼中一個履行這一義務的函數——f

void f()

{

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

  ...                                        // 使用pInv

  delete pInv;                               // 釋放該對象

}

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

當然,用心編程就有可能防止這類錯誤發生,但是請想象一下代碼會多么的不固定——你需要不停地修改代碼。隨著軟件不斷得到維護,為一個函數添加returncontinue語句可能會對其資源管理策略造成怎樣的影響呢,一些人可能由于不完全理解這一問題就這樣做了。還有更嚴重的,就是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是這樣的智能指針:它可以跟蹤有多少的對象指向了一個特定的資源,同時當沒有指針在指向這一資源時,智能指針會自動刪除該資源??梢钥闯觯琑CSP的行為與垃圾回收器很相似。然而,與垃圾回收器不同的是,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);

                                    // 現在pInv1pInv2均指向同一對象

 

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

  ...

}                                   // pInv1pInv2被銷毀,

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

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

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

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

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

                                   // 壞主意!

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

 

std::tr1::shared_ptr<int> spi(new int[1024]);

                                   // 同樣的問題

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

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

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

時刻牢記

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

auto_ptrtr1::shared_ptr是兩個常用并且實用的RAII類。通常情況下tr1::shared_ptr是更好的選擇,因為它的復制行為更加直觀。復制一個auto_ptr將會使其重設為null。

posted on 2007-05-07 18:52 ★ROY★ 閱讀(1016) 評論(0)  編輯 收藏 引用 所屬分類: Effective C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            午夜精品亚洲一区二区三区嫩草| 国产精品一区一区| 亚洲精品久久久一区二区三区| 欧美黄色片免费观看| 麻豆亚洲精品| 亚洲先锋成人| 欧美一区午夜视频在线观看| 亚洲成色www8888| 亚洲国产日韩一区二区| 欧美日产在线观看| 欧美一区二区在线免费播放| 久久精品毛片| 一区二区日韩伦理片| 亚洲欧美日韩精品久久亚洲区| 精品88久久久久88久久久| 欧美激情国产精品| 国产精品狼人久久影院观看方式| 久久久人成影片一区二区三区观看| 久久一区欧美| 小黄鸭精品密入口导航| 老鸭窝亚洲一区二区三区| 中文日韩欧美| 久久免费国产精品| 亚洲制服少妇| 欧美大色视频| 久久一区二区视频| 欧美午夜电影在线观看| 欧美.www| 国产精品久久久久久亚洲调教| 欧美日韩国产不卡| 久久国产一区| 欧美日本国产精品| 久久亚洲春色中文字幕| 欧美日韩一级大片网址| 欧美a级一区| 国产欧亚日韩视频| 一本久道久久综合中文字幕| 亚洲精品乱码久久久久久日本蜜臀| 国产精品久久久久毛片软件| 免费永久网站黄欧美| 国产精品自拍小视频| 亚洲精品一区在线观看| 亚洲国产精品电影| 久久精品国产免费观看| 欧美一区二区精品| 欧美视频一区二区| 亚洲黄色免费| 91久久视频| 久久综合九色综合久99| 久久久蜜桃一区二区人| 国产毛片久久| 亚洲女人天堂av| 午夜视频精品| 国产精品欧美经典| 亚洲视频每日更新| 亚洲一区二区三区色| 欧美日韩亚洲91| 亚洲日韩中文字幕在线播放| 亚洲日韩视频| 欧美精品激情在线观看| 亚洲国产精品激情在线观看| 亚洲国产精品久久精品怡红院| 久久噜噜噜精品国产亚洲综合| 久久夜色精品一区| 亚洲国产mv| 欧美二区不卡| 99爱精品视频| 午夜精品久久久久久久99黑人| 国产精品草莓在线免费观看| 亚洲一区bb| 久久久久久亚洲精品中文字幕| 国产欧美一区二区三区沐欲| 欧美一级久久| 欧美性事免费在线观看| 亚洲一区二区视频在线| 欧美一级大片在线观看| 国产在线精品成人一区二区三区| 久久九九国产精品| 最新亚洲激情| 午夜精品美女久久久久av福利| 国产欧美va欧美不卡在线| 久久精品成人一区二区三区蜜臀 | 久热精品视频在线观看一区| 母乳一区在线观看| 亚洲精品中文字| 国产精品久久久久7777婷婷| 欧美一区二区三区在线免费观看| 母乳一区在线观看| 正在播放亚洲| 韩国av一区二区三区四区| 欧美1区2区视频| 亚洲性夜色噜噜噜7777| 蜜臀久久99精品久久久久久9 | 精品99一区二区三区| 欧美激情一区二区三区成人 | 欧美激情一区二区三区四区| 国产精品99久久久久久久久| 国产视频在线观看一区二区三区| 每日更新成人在线视频| 亚洲视频免费在线| 欧美国产专区| 欧美亚洲一区三区| 亚洲激情欧美激情| 国产精品久久久久天堂| 久久亚洲国产成人| 亚洲欧美日韩国产一区| 亚洲国产导航| 久久人人爽人人爽| 欧美一级片一区| 欧美成人情趣视频| 新狼窝色av性久久久久久| 国产亚洲毛片在线| 国产精品video| 欧美激情欧美激情在线五月| 久久av最新网址| 亚洲一区美女视频在线观看免费| 亚洲成人资源| 久热这里只精品99re8久| 亚洲一区三区视频在线观看| 亚洲欧洲精品一区二区三区不卡| 国产一区二区av| 久久九九国产精品怡红院| 午夜精品久久久久久99热软件| 亚洲国产一区二区三区在线播| 久久这里只有| 久久久噜噜噜久久| 欧美综合国产| 欧美一级午夜免费电影| 亚洲一级在线观看| 一区二区三区视频观看| 日韩午夜在线视频| 亚洲美女电影在线| 亚洲乱码精品一二三四区日韩在线| 狠狠色狠狠色综合日日小说| 国产日韩欧美夫妻视频在线观看| 国产精品成人va在线观看| 欧美日韩精品是欧美日韩精品| 欧美高潮视频| 欧美精品在线观看播放| 欧美激情精品久久久六区热门| 免费观看成人| 欧美精品免费视频| 欧美精品一区二区在线播放| 欧美久久影院| 国产精品二区三区四区| 国产精品乱人伦中文| 国产精品免费看片| 国产精品网站一区| 国产一区二区三区在线观看免费| 国产亚洲第一区| 影音先锋欧美精品| 91久久精品国产91性色tv| 亚洲精品视频免费| 亚洲一区二区高清| 欧美一区二区三区视频在线| 欧美一区影院| 欧美成人午夜激情| 亚洲精选久久| 午夜精品久久久久久久久| 欧美在线free| 欧美黄色一区| 国产精品三级久久久久久电影| 国产精品制服诱惑| 136国产福利精品导航网址| 亚洲乱码国产乱码精品精| 亚洲一区精品视频| 久久中文在线| 一本久道综合久久精品| 欧美在线综合视频| 夜夜嗨av一区二区三区网站四季av| 亚洲午夜视频在线观看| 久久精品亚洲精品| 欧美日韩免费精品| 黄色成人在线网址| 一本色道久久综合狠狠躁篇的优点| 亚洲欧美视频| 欧美激情视频一区二区三区在线播放| 国模套图日韩精品一区二区| 亚洲国产精品第一区二区| 亚洲在线视频免费观看| 麻豆国产精品一区二区三区| 亚洲免费久久| 久久久久久穴| 欧美调教vk| 91久久中文字幕| 久久九九精品99国产精品| 亚洲剧情一区二区| 久久久久青草大香线综合精品| 欧美日韩国产综合视频在线观看中文 | 国产一区二区三区精品欧美日韩一区二区三区| 精品91免费| 久久狠狠一本精品综合网| 亚洲激情视频网站| 久久―日本道色综合久久| 国产欧美日韩视频在线观看| 日韩午夜电影av| 欧美激情精品久久久久| 欧美在线黄色| 国产日韩一区二区| 午夜精品久久久久久久白皮肤 |