C 中的RAII機制

2021-09-25 11:44:57 字數 2384 閱讀 6937

前言

在寫c++設計模式——單例模式的時候,在寫到例項銷毀時,設計的gc類是很巧妙的,而這一巧妙的設計就是根據當物件的生命週期結束時會自動呼叫其析構函式的,而這一巧妙的設計也是有專業的名詞的——raii。那以下將圍繞raii,全面的講解raii的相關知識。

什麼是raii?

raii是resource acquisition is initialization的簡稱,是c++語言的一種管理資源、避免洩漏的慣用法。利用的就是c++構造的物件最終會被銷毀的原則。raii的做法是使用乙個物件,在其構造時獲取對應的資源,在物件生命期內控制對資源的訪問,使之始終保持有效,最後在物件析構的時候,釋放構造時獲取的資源。

為什麼要使用raii?

上面說到raii是用來管理資源、避免資源洩漏的方法。那麼,用了這麼久了,也寫了這麼多程式了,口頭上經常會說資源,那麼資源是如何定義的?在計算機系統中,資源是數量有限且對系統正常執行具有一定作用的元素。比如:網路套接字、互斥鎖、檔案控制代碼和記憶體等等,它們屬於系統資源。由於系統的資源是有限的,就好比自然界的石油,鐵礦一樣,不是取之不盡,用之不竭的,所以,我們在程式設計使用系統資源時,都必須遵循乙個步驟:

申請資源;

使用資源;

釋放資源。

第一步和第二步缺一不可,因為資源必須要申請才能使用的,使用完成以後,必須要釋放,如果不釋放的話,就會造成資源洩漏。

乙個最簡單的例子:

#includeusingnamespacestd;intmain()

我們使用new開闢的記憶體資源,如果我們不進行釋放的話,就會造成記憶體洩漏。所以,在程式設計的時候,new和delete操作總是匹配操作的。如果總是申請資源而不釋放資源,最終會導致資源全部被占用而沒有資源可用的場景。但是,在實際的程式設計中,我們總是會各種不小心的就把釋放操作忘了,就是程式設計的老手,在幾千行**,幾萬行中**中,也會犯這種低階的錯誤。

再來乙個例子:

#includeusingnamespacestd;booloperationa();booloperationb();intmain()if(!operationb())// all the operation succeed, delete the memory deletetestarray;testarray =null ;return0;}booloperationa()booloperationb()

上述這個例子的模型,在實際中是經常使用的,我們不能期待每個操作都是成功返回的,所以,每乙個操作,我們需要做出判斷,上述例子中,當操作失敗時,然後,釋放記憶體,返回程式。上述的**,極度臃腫,效率下降,更可怕的是,程式的可理解性和可維護性明顯降低了,當操作增多時,處理資源釋放的**就會越來越多,越來越亂。如果某乙個操作發生了異常而導致釋放資源的語句沒有被呼叫,怎麼辦?這個時候,raii機制就可以派上用場了。

如何使用raii?

當我們在乙個函式內部使用區域性變數,當退出了這個區域性變數的作用域時,這個變數也就別銷毀了;當這個變數是類物件時,這個時候,就會自動呼叫這個類的析構函式,而這一切都是自動發生的,不要程式設計師顯示的去呼叫完成。這個也太好了,raii就是這樣去完成的。由於系統的資源不具有自動釋放的功能,而c++中的類具有自動呼叫析構函式的功能。如果把資源用類進行封裝起來,對資源操作都封裝在類的內部,在析構函式中進行釋放資源。當定義的區域性變數的生命結束時,它的析構函式就會自動的被呼叫,如此,就不用程式設計師顯示的去呼叫釋放資源的操作了。現在,我們就用raii機制來完成上面的例子。**如下:

上面這個例子沒有多大的實際意義,只是為了說明raii的機制問題。下面說乙個具有實際意義的例子:

/*

** filename : raii

** author : jelly young

** date : 2013/11/24

** description : more information, please go to

*/#include#include#includeusingnamespacestd;critical_section cs;intgglobal =0;classmylock~mylock()private:mylock(constmylock&);mylockoperator=(constmylock&);};voiddocomplex(mylock&lock)// 非常感謝益可達犀利的review 2014.04.13{}unsignedint__stdcall threadfun(pvoid pv)return0;}intmain(){initializecriticalsection(&cs);intthread1,thread2;thread1 =1;thread2 =2;handle handle[2];handle[0]=(handle )_beginthreadex(null ,0,threadfun,(void

C 中RAII機制的介紹與簡單例項

今天看陳碩的多執行緒書上提到了c 中raii技術的使用,通過用c11裡面自帶的智慧型指標來完成對資源的控制,但是一直不太清楚具體raii是怎麼樣的,帶著這樣的疑問,特地去看了幾篇部落格,找了乙個簡單的檔案控制代碼開啟關閉raii管理的例項,瞬間就明白了,這裡分享出來。主要從兩個部分,首先是raii技...

C 中的RAII用法

c 中的raii全稱是 resource acquisition is initialization 直譯為 資源獲取就是初始化 但是這翻譯並沒有顯示出這個慣用法的真正內涵。raii的好處在於它提供了一種資源自動管理的方式,當產生異常 回滾等現象時,raii可以正確地釋放掉資源。舉個常見的例子 cp...

C 中的RAII介紹

raii技術被認為是c 中管理資源的最佳方法,進一步引申,使用raii技術也可以實現安全 簡潔的狀態管理,編寫出優雅的異常安全的 raii是c 的發明者bjarne stroustrup提出的概念,raii全稱是 resource acquisition is initialization 直譯過來...