讀書筆記effectivec++Item13用對象來管理資源-創(chuàng)新互聯(lián)

正文

創(chuàng)新互聯(lián)公司-專業(yè)網站定制、快速模板網站建設、高性價比昭陽網站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式昭陽網站制作公司更省心,省錢,快速模板網站建設找我們,業(yè)務覆蓋昭陽地區(qū)。費用合理售后完善,10多年實體公司更值得信賴。

回到頂部

1.不要手動釋放從函數(shù)返回的堆資源

假設你正在處理一個模擬Investment的程序庫,不同的Investmetn類型從Investment基類繼承而來,

1 class Investment { ... }; // root class of hierarchy of2 3 // investment types

進一步假設這個程序庫通過一個工廠函數(shù)(Item 7)來給我們提供特定Investment對象:

讀書筆記 effective c++ Item 13 用對象來管理資源

1 Investment* createInvestment(); // return ptr to dynamically allocated2 3 // object in the Investment hierarchy;4 5 // the caller must delete it6 7 // (parameters omitted for simplicity)

讀書筆記 effective c++ Item 13 用對象來管理資源

正如注釋所表述的,當createInvesment返回的對象不再被使用時,調用者有責任將此對象釋放掉。我們用函數(shù)f來履行這個職責:

讀書筆記 effective c++ Item 13 用對象來管理資源

 1 void f() 2  3 { 4  5 Investment *pInv = createInvestment(); // call factory function 6  7 ... // use pInv 8  9 delete pInv; // release object10 11 }

讀書筆記 effective c++ Item 13 用對象來管理資源

這個方法看上去挺好,但是在一些情況下釋放從createInvestment得來的對象有可能會失敗。在函數(shù)的”…”部分中有可能會出現(xiàn)過早的reture語句,如果這個return被執(zhí)行了,那么最后的delete語句永遠不會被執(zhí)行到;如果createInvesment和delete在一個循環(huán)中,break和goto語句會使循環(huán)過早退出,delete也不會被執(zhí)行到;最后在…中的一些語句有可能會拋出異常,如果這樣的話,控制流程會再次不能執(zhí)行到delete。不管delete是怎么被跳過去的,不僅會泄露Invesment對象所使用的內存,也會泄露Investment對象所擁有的任何資源。

當然,小心的編程可以防止這類錯誤的發(fā)生,但是你應該想到隨著時間的推移代碼有可能發(fā)生變化。在軟件的維護過程中,一些人可能在沒有完全領會這個函數(shù)的資源管理策略的情況下為其添加一個return或者continue語句。更糟糕的是,f函數(shù)的”…”部分有可能調用一個從來沒有拋出異常的函數(shù),但這個函數(shù)被“改善”后,它拋出異常了。所以依賴f來到達delete語句通常是不可行的。

回到頂部

2.通過對象來管理需要手動釋放的資源

為了確保從createInvestment返回的資源總是被釋放,我們需要將資源放到一個對象中,當離開函數(shù)f的時候,對象的析構函數(shù)會自動釋放對象擁有的資源。事實上,我們已經說出了這個條款一半的內容:通過將資源放入對象中,我們可以依賴c++的析構函數(shù)自動調用機制來確保資源被釋放。(另一半一會就會講到)

2.1 使用auto_ptr來管理資源

許多資源是被動態(tài)的分配在堆上的,它們被用在一個單獨的塊或者函數(shù)中,當控制流離開塊或者函數(shù)時,這些資源應該被釋放。標準庫中的auto_ptr正是為這種情況量身定做的。Auto_ptr是一個指針(智能指針)一樣的對象,它的析構函數(shù)會自動為其指向的對象調用delete函數(shù)。下面演示如何使用auto_ptr來防止可能出現(xiàn)的資源泄露:

讀書筆記 effective c++ Item 13 用對象來管理資源

 1 void f() 2  3 { 4  5 std::auto_ptr<Investment> pInv(createInvestment()); // call factory 6  7 // function 8  9 ... // use pInv as10 11 // before12 13 } // automatically14 15 // delete pInv via16 17 // auto_ptr’s dtor

讀書筆記 effective c++ Item 13 用對象來管理資源

2.2 用對象管理資源的兩個關鍵點

這個簡單的例子指出了使用對象管理資源的兩個關鍵點:

  • 獲取資源后應該立即將其轉交給資源管理對象。從上面的例子看出,使用createInvestment返回的資源來初始化對其進行管理的auto_ptr指針。事實上,用對象來管理資源的想法通常被叫做”資源獲取的時候就是初始化的時候”(Resource Acquisition Is Initialization RAII),因為將資源獲取和資源管理對象的初始化放在同一個語句中是非常常見的。有時用獲取的資源給資源管理對象賦值而不是初始化,但是不管哪種方法,都是在資源獲取到之后馬上將控制權轉交給資源管理對象。

  • 資源管理對象使用它們的析構函數(shù)來確保資源被釋放。因為不管控制流是怎么離開塊或函數(shù)的,對象銷毀的時候析構函數(shù)會被自動調用(例如當一個對象超出了作用域),資源因此能夠被正確釋放。釋放資源時拋出異常會使問題變的棘手,這個問題在Item8中討論了,我們不再擔心這種問題。

因為 當auto_ptr被銷毀時會自動delete它所指向的資源,所以有沒有多個auto_ptr指向通一個對象是很重要的。如果有多個,對象會被多次delete,這就會導致出現(xiàn)未定義行為。為了防止這樣的問題出現(xiàn),auto_ptrs有一個與眾不同的性質:被拷貝的指針(通過拷貝構造函數(shù)或者拷貝賦值運算符)會被置為null,進行拷貝的指針將擁有資源的所有權。

讀書筆記 effective c++ Item 13 用對象來管理資源

 1 std::auto_ptr<Investment> // pInv1 points to the 2  3 pInv1(createInvestment()); // object returned from 4  5 // createInvestment 6  7 std::auto_ptr<Investment> pInv2(pInv1); // pInv2 now points to the 8  9 // object; pInv1 is now null10 11 pInv1 = pInv2; // now pInv1 points to the12 13 // object, and pInv2 is null

讀書筆記 effective c++ Item 13 用對象來管理資源

2.3 用shared_ptr來管理資源

奇特的拷貝行為,加上“不能有超過一個的auto_ptr指向被auto_ptr管理的資源”,這兩種特性使得auto_ptrs不是管理所有動態(tài)分配資源的最好方法。舉個例子,STL容器需要”正常的”拷貝行為,因此就不能將容器放入auto_ptr中。

Auto_ptr的一種替代方法是使用“引用計數(shù)的智能指針”(reference-counting smart pointer RCSP).RCSP是一種能夠跟蹤有多少對象指向同個一特定資源的指針,資源只有在沒有指針指向的情況下才能被釋放。因此,RCSP提供的行為同垃圾回收機制類似。和垃圾回收機制不同的是,RCSP不會制止循環(huán)引用(例如,兩個都不被使用的對象卻指向彼此,看上去在被使用一樣。)

TR1的tr1::shared_ptr(看Item54)是是一個RCSP,所以你可以這么實現(xiàn)f:

讀書筆記 effective c++ Item 13 用對象來管理資源

 1 void f() 2  3 { 4  5 ... 6  7 std::tr1::shared_ptr<Investment> 8  9 pInv(createInvestment()); // call factory function10 11 ... // use pInv as before12 13 } // automatically delete14 15 // pInv via shared_ptr’s dtor

讀書筆記 effective c++ Item 13 用對象來管理資源

這段代碼看上去同使用auto_ptr大致相同,但是拷貝shared_ptrs的行為更加自然:

讀書筆記 effective c++ Item 13 用對象來管理資源

 1 void f() 2  3 { 4  5 ... 6  7 std::tr1::shared_ptr<Investment> // pInv1 points to the 8  9 pInv1(createInvestment()); // object returned from10 11 // createInvestment12 13 std::tr1::shared_ptr<Investment> // both pInv1 and pInv2 now14 pInv2(pInv1); // point to the object15 pInv1 = pInv2; // ditto — nothing has16 // changed17 ...18 } // pInv1 and pInv2 are19 // destroyed, and the20 // object they point to is21 // automatically deleted

讀書筆記 effective c++ Item 13 用對象來管理資源

因為拷貝tr1::shared_ptrs的工作方式是你所想要的,它們可以被用在像STL容器和其他上下文中,在這里auto_ptr的古怪的拷貝方式不再合適。

2.4 不要將auto_ptr和shared_ptr用于動態(tài)分配數(shù)組

不要被誤導。這個條款不是用來介紹關于auto_ptr,tr1::shared_ptr或者其它類型的智能指針。這個條款講述的是用對象管理資源的重要性。使用Auto_ptr和tr1::shared_ptr只是舉個例子。(關于tr1::shared_ptr的更多內容,查看Item14 18和54)

Auto_ptr和tr1::shared_ptr的析構函數(shù)中使用的是delete而不是delete[]。(Item16 描述了區(qū)別)這意味著在auto_ptr或者tr1::shared_ptr中存放動態(tài)分配的數(shù)組不是一個好方法,令人遺憾的是,這種用法可以通過編譯:

1 std::auto_ptr<std::string> // bad idea! the wrong2 3 aps(new std::string[10]); // delete form will be used4 5 std::tr1::shared_ptr<int> spi(new int[1024]); // same problem

你會驚奇的發(fā)現(xiàn)c++中沒有用于動態(tài)分配數(shù)組的類似auto_ptr或者tr1::shared_ptr的東西,TR1中也沒有。因為vector和string基本可以替代動態(tài)分配數(shù)組了。如果你仍然認為存在用于動態(tài)分配數(shù)組的類似于auto_ptr和tr1::shared_ptr的類是好的,可以看一下Boost(Item 55).你會非常高興的發(fā)現(xiàn)boost::scoped_array和boost::shared_array類提供了你正在尋找的。

回到頂部

3.其他問題

這個條款中,使用對象管理資源的指導方針意味著如果你自己手動釋放資源(例如使用delete而不是一個資源管理類),你的做法就是錯誤的。 預裝的資源管理類,像auto_ptr和tr1::shared_ptr使遵守這個條款變的更加容易,但有時候當你使用一個資源的時候你會發(fā)現(xiàn)這些預制的類沒有做到你想要的。這種情況下,你就需要編寫你自己的資源管理類了。這也不是非常難的,但確實有一些微妙的地方需要你考慮。這些注意點將要在Item14和Item15種進行討論。

最后,我必須指出createInvestment的原生指針返回類型是資源泄露的×××,因為調用者很容易就會忘記調用delete(即使使用auto_ptr和tr1::shared_ptr來執(zhí)行delete,它們仍然需要記得將createInvestment的返回值放入智能指針對象中)。對付這個問題需要調用createInvestment的修訂版本,這個問題會在Item18中進行討論。

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

新聞標題:讀書筆記effectivec++Item13用對象來管理資源-創(chuàng)新互聯(lián)
網頁地址:http://muchs.cn/article26/cocpjg.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、App設計云服務器、用戶體驗、品牌網站制作、建站公司

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化