• <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>

            Shuffy

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

            第17條:     要在單獨的語句中使用智能指針來存儲由 new 創建的對象

            假設這里有一個函數用來顯示處理優先級,另一個函數根據當前優先級為一個動態分配的 Widget 做一些處理:

            int priority();

            void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);

            一定要時刻記住“使用對象管理資源”這一真理(參見第 13 條)。 processWidget 中可以使用智能指針來動態分配其需要處理的 Widget

            下面是對 progressWidget 的一次調用:

            processWidget(new Widget, priority());

            請稍等,不要試圖這樣調用。這將不會通過編譯。 tr1::shared_ptr 的構造函數中包含了一個 explicit 的裸指針,于是便不存在從“ new Widget ”語句返回的裸指針到 processWidget 所需的 tr1::shared_ptr 的隱式轉換。然而下邊的代碼將順利通過編譯:

            processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());

            看上去有些令人吃驚,盡管我們時時刻刻使用對象來管理資源,但是這里還是有出現資源泄漏的可能。了解這些發生的原由對我們深入理解是有一定幫助的。

            在編譯器能夠生成對 processWidget 的調用之前,它必須評估傳入的參數。第二個參數僅僅調用了一個函數 priority ,但是第一個參數(“ std::tr1::shared_ptr<Widget>(new Widget) ”)包含兩部分:

            運行 “new Widget” 語句

            調用 tr1::shared_ptr 的構造函數

            因此,在 processWidget 可以被調用之前,編譯器必須自動生成代碼來解決下面的三件事情:

            調用 priority

            執行 “new Widget”

            調用 tr1::shared_ptr 的構造函數。

            C++ 編譯器對于這三項任務完成的順序要求得很寬松。(這一點與 Java C# 就很不一樣了,這兩門語言中的函數參數總是以一個特定的順序得到評估。)由于“ new Widget ”語句為 tr1::shared_ptr 的構造函數傳遞了一個參數,因此它必須在 tr1::shared_ptr 的構造函數被調用之前得到執行。但是調用 priority 的工作可以放到第一,第二,也可以放在最后。如果編譯器決定第二個處理它(這樣可以使代碼更高效),我們就會得到這樣的執行序列:

            1. 執行 new Widget .

            2. 調用 priority

            3. 調用 tr1::shared_ptr 的構造函數。

            但是請想象一下如果調用 priority 時拋出了一個異常的話,將會發生些什么。在這種情況下,由于“ new Widget ”返回的指針不會如我們所愿保存在 tr1::shared_ptr 中,因此它很有可能會丟失,于是內存泄漏就發生了。在資源被創建以后和這個資源轉交給一個資源管理對象之前的這段時間內,有可能發生異常,如果發生的話,那么調用 processWidget 就會造成資源泄漏。

            防止這類問題發生的辦法很簡單:使用單獨的語句,創建 Widget 并將其存入一個智能指針,然后將這個智能指針傳遞給 processWidget

            std::tr1::shared_ptr<Widget> pw(new Widget);

                                               // 在一個單獨的語句中創建 Widget

                                               // 并存入一個智能指針

             

            processWidget(pw, priority());     // 這樣調用就不會泄漏了。

            這樣是可行的,因為編譯器為多行的語句安排執行順序要比單一的語句時嚴格得多。由于這段改進的代碼中,“ new Widget ”語句以及對 tr1::shared_ptr 的構造函數的調用在單獨的語句中,對 priority 的調用在另一個單獨的語句中,所以編譯器就沒有機會調換處理順序了。

            牢記在心

            在單獨的語句中使用智能指針來保存由 new 創建的對象。如果不這樣做,你的程序會在拋出異常時發生資源泄漏。

            亚洲中文字幕久久精品无码APP | 久久99这里只有精品国产| 91久久精品无码一区二区毛片| 久久青草国产手机看片福利盒子| 国内精品久久久久久久涩爱 | 久久久久国产亚洲AV麻豆| 四虎国产精品成人免费久久| 精品无码久久久久久尤物| 久久91亚洲人成电影网站| 狠狠色丁香婷婷久久综合| 国产精品禁18久久久夂久| 一极黄色视频久久网站| 99久久久国产精品免费无卡顿| 日韩美女18网站久久精品| 91精品国产综合久久婷婷| 久久人妻少妇嫩草AV蜜桃| 国产精品免费福利久久| 亚洲国产成人久久一区久久| 曰曰摸天天摸人人看久久久| 亚洲午夜久久久影院| 久久久久久免费视频| 久久精品国产只有精品66| 99久久婷婷免费国产综合精品| 久久久久亚洲AV无码专区首JN | 伊人久久大香线蕉av一区| 久久久久亚洲爆乳少妇无| 国产福利电影一区二区三区久久久久成人精品综合 | 久久国产乱子伦精品免费强| 欧美亚洲国产精品久久| 久久精品国产黑森林| 欧美综合天天夜夜久久| 国产综合久久久久久鬼色| 久久久精品人妻一区二区三区四 | 天天久久狠狠色综合| 久久精品国产精品国产精品污| 无码精品久久久久久人妻中字| 亚洲欧美成人综合久久久| 亚洲午夜久久久久妓女影院| 国产精品美女久久福利网站| 久久精品国产亚洲AV香蕉| 亚洲AV无一区二区三区久久|