C++中沒有finally,那么應該在哪里關閉資源?


 

這是一篇有趣的帖子

原文鏈接: http://bbs.csdn.net/topics/90070457

樓主:

C++中沒有finally,那么應該在哪里關閉資源?

C++的try{}catch(){},為什么沒有finally{}塊來釋放資源?
如類中的一個方法,局部變量
File * file=NULL;
Try{
file=fopen(“aaa.txt”,”r”);
然后執行一些操作。
}
最后fclose(file);
假如,file操作時發生異常,需要關閉。對於Java來說,是在finally{}塊中關閉。不論是否發生異常,一定會關閉!
而C++中呢,怎樣保證一定關閉這個文件呢?

大牛A:

在C++中通常使用RAII,即Resource Aquisition Is Initialization.
就是將資源封裝成一個類,將資源的初始化封裝在構造函數里,釋放封裝在析構函數里。要在局部使用資源的時候,就實例化一個local object。
在拋出異常的時候,由於local object脫離了作用域,自動調用析構函數,會保證資源被釋放

簡單的例子:
try {
   File f("xxx.ttt");
    //other file operation
}//File pointer is released here
catch {
    //exception process
}

大牛B:

Polarislee(北極星)(北京那么大,何處是我家)說的“在拋出異常的時候,由於local object脫離了作用域,自動調用析構函數,會保證資源被釋放”有個名字,叫“棧展開”,就是在“彈棧”時候自動將棧中構造好的對象析構,這樣就可以保證沒有“資源泄漏”了。

大牛C:

說 C++ 有 finally 的全部認定為 Java/C# 奸細;說 C++ 有 __finally 的全部認定為 MS 奸細…… ^^

標准 C++ 是沒有類似 finally 這樣的語句結構的。C# / Java 中保證無論是否出現異常,finally block 的代碼均會得到執行;而 C++ 中,不論是否出現異常,局部變量的析構函數是會保證執行的,所以相對應與 finally block,C++ 的解決辦法就是 PolarisLee 大俠說的 RAII 了。

大牛A:

RAII立用的是棧變量會在離開作用域的時候自動析構的原理。樓上大部分提到智能指針的人都只關注了內存泄露,但是樓主說得是資源管理,比如文件句柄和Socket之類的東西,只能指針在這里是無能為力的。

另外帶下划線的__try{}__catch{}__finally{}是Windows系統的標准異常處理,它不是C++標准的語法,而是用來捕獲和處理一些Windows系統產生的異常,如:內存訪問越界、除0異常等。

至於認為封裝資源寫一個類太麻煩的人不妨這樣想:
如果是一個大系統,一類資源可能使用的地方有成千上萬,那么這種封裝帶來的好處遠遠大於寫一個類的麻煩,不是嗎:)

大牛D:

用RAII,就是包裝一下資源,使用析構函數被編譯器自動調用的好處
包裝類也就保存的是資源的句柄,就如你使用一個int變量一樣
難不成你int也要new嗎,其實這應該是<<imperfect c++>>中所說的RRID,
資源釋放即析構,包裝類接受外部的資源句柄,在析構函數中進行釋放,這也是c++的美妙之處
如果有finally,始終記着關閉資源也是件很煩的事,
所以C#中雖然有finally,但也提供了
using ( A a = new A() )
{
}
這種類型的,超出它的作用域會調用它的dispose函數
這讓程序看起來很優雅

大牛E:

使用C/C++的人,都該有這么一個共識:對資源誰申請誰釋放,否則就必須使用委托。當資源僅在某一個函數里使用時,那就必須在該函數里釋放

C++里並不需要finally,有關java里所說的問題,在C++中是不存在的,相反,有了那種東西反而會帶來問題,因為finally設置本身就是一種無用的垃圾。我前面說過了,java里有那種東西是一種沒得辦法的辦法,純屬無奈之舉,在C++里還把它當寶貝似的顯眼,一窩蜂的跟風,不讓人笑話嗎!
況且,更重要的是,java所運用的finally機制並不安全,如果現在就有量子計算機,那首先就是個漏洞。目前之所以還沒有暴露其危害性,還跟關鍵領域應用少有關。

大牛F:

__try, __except 和 __finally 是Windows的SEH機制,和語言無關。

而 try 和 catch 是C++的異常處理機制。

C沒有提供語言級別的異常處理機制。

大牛G調侃說:

介紹一個最簡單的方法來關閉資源,非常有效 --> 按住Power超過4秒鍾, 所有的資源都自動釋放掉了. 

干脆就define一個final空宏好了. 
然后也可以寫成
#ifndef final
#define final
#endif

FILE* file;
try
{....
}
catch(...)
{....
}
final
{....
}
語法上沒有問題. 

呵呵

大牛H:

finally並不是標准C++的一部分,現在大家所試用的_finally是各個編譯器廠商的擴充.<The C++ Programming Language>作者Bjarne Stroustrup認為finally在C++里面是多余的,它所作的工作應該由析構函數來作.

倔強的樓主最后說:

我決定使用Boost的智能指針方案。
Loki的scopeGuard太先進了,不會。
Hp的GC方案,太難看了。侵入性太強。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM