日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ RAII

發布時間:2025/4/5 c/c++ 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ RAII 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么80%的碼農都做不了架構師?>>> ??

C++?RAII

????RAII是resource?acquisition?is?initialization的縮寫,意為“資源獲取即初始化”。它是C++之父Bjarne?Stroustrup提出的設計理念,其核心是把資源和對象的生命周期綁定,對象創建獲取資源,對象銷毀釋放資源。在RAII的指導下,C++把底層的資源管理問題提升到了對象生命周期管理的更高層次。
????說起來,RAII的含義倒也不算復雜。用白話說就是:在類的構造函數中分配資源,在析構函數中釋放資源。這樣,當一個對象創建的時候,構造函數會自動地被調用;而當這個對象被釋放的時候,析構函數也會被自動調用。于是乎,一個對象的生命期結束后將會不再占用資源,資源的使用是安全可靠的。
C++?RAII體現出了簡潔、安全、實時的特點:

1.概念簡潔性:讓資源(包括內存和非內存資源)和對象的生命周期綁定,資源類的設計者只需用在類定義內部處理資源問題,提高了程序的可維護性
2.類型安全性:通過資源代理對象包裝資源(指針變量),并利用運算符重載提供指針運算方便使用,但對外暴露類型安全的接口
3.異常安全性:棧語義保證對象析構函數的調用,提高了程序的健壯性
4.釋放實時性:和GC相比,RAII達到了和手動釋放資源一樣的實時性,因此可以承擔底層開發的重任

也許你還在驚訝RAII如此簡單的時候,關于RAII的主要內容已經介紹完了。簡單不意味著簡陋,在我看來RAII雖然不像GC一樣,是一套具體的機制,但它蘊含的對象與資源關系的哲學深度的理解卻使得我對Bjarne?Stroustrup肅然起敬!

最后,不得不提醒RAII的理念固然簡單,不過在具體實現的時候仍有需要小心的地方。比如對于STL的auto_ptr,可以視為資源的代理對象,auto_ptr對象間的賦值是一個需要特別注意的地方。簡單說來資源代理對象間賦值的語義不滿足“賦值相等”,其語義是資源管理權的轉移。

什么是“賦值相等”呢?比如:

int?a;??int?b?=?10;??a?=?b;?//這句話執行后?a?==?b?但對于資源代理對象,這是不滿足的,比如:

auto_ptr<int>?a(null);??auto_ptr<int>?b(new?int(123));??a?=?b;?//這句話執行后a?!=?b,賦值的語義是b把資源的管理權交給了a?

auto_ptr是這樣一種指針:它是“它所指向的對象”的擁有者。這種擁有具有唯一性,即一個對象只能有一個擁有者,嚴禁一物二主。當auto_ptr指針被摧毀時,它所指向的對象也將被隱式銷毀,即使程序中有異常發生,auto_ptr所指向的對象也將被銷毀。


關于auto_ptr的幾種注意事項:
1、auto_ptr不能共享所有權。
2、auto_ptr不能指向數組
3、auto_ptr不能作為容器的成員。
4、不能通過賦值操作來初始化auto_ptr
std::auto_ptr<int>?p(new?int(42));?????//OK
std::auto_ptr<int>?p?=?new?int(42);????//ERROR
這是因為auto_ptr?的構造函數被定義為了explicit
5、不要把auto_ptr放入容器

下面便是在C++中實現RAII的典型代碼:
class?file
{
public:
????file(string?const&?name)?{
????????m_fileHandle=fopen(name.cstr());
????}
????~file()?{
????????fclose(m_fileHandle);
????}
????//
private:
????handle?m_fileHandle;
}

很典型的“在構造函數里獲取,在析構函數里釋放”。如果我寫下代碼:???
void?fun1()?{
????file?myfile("my.txt");
?????//操作文件
}?//此處銷毀對象,調用析構函數,釋放資源
當函數結束時,局部對象myfile的生命周期也結束了,析構函數便會被調用,資源會得到釋放。而且,如果函數中的代碼拋出異常,那么析構函數也會被調用,資源同樣會得到釋放。所以,在RAII下,不僅僅資源安全,也是異常安全的。

但是,在如下的代碼中,資源不是安全的,盡管我們實現了RAII:
void?fun2()?{
????file?pfile=new?file("my.txt");
?????//操作文件
}
因為我們在堆上創建了一個對象(通過new),但是卻沒有釋放它。我們必須運用delete操作符顯式地加以釋放:
void?fun3()?{
????file?pfile=new?file("my.txt");
?????//操作文件
????????delete?pfile;
}
否則,非但對象中的資源得不到釋放,連對象本身的內存也得不到回收。(將來,C++的標準中將會引入GC(垃圾收集),但正如下面分析的那樣,GC依然無法確保資源的安全)。
現在,在fun3(),資源是安全的,但卻不是異常安全的。因為一旦函數中拋出異常,那么delete?pfile;這句代碼將沒有機會被執行。

C++領域的諸位大牛們告誡我們:如果想要在沒有GC的情況下確保資源安全和異常安全,那么請使用智能指針:
void?fun4()?{
????auto_ptr<file>?spfile(new?file("my.txt"));
?????//操作文件
}?//此處,spfile結束生命周期的時候,會釋放(delete)對象
那么,智能指針又是怎么做到的呢?下面的代碼告訴你其中的把戲(關于智能指針的更進一步的內容,請參考std::auto_ptr,boost或shared_ptr的智能指針)。
也就是說,智能指針通過RAII來確保內存資源的安全,也間接地使得對象上的RAII得到實施。不過,這里的RAII并不是十分嚴格:對象(所占的內存也是資源)的創建(資源獲取)是在構造函數之外進行的。廣義上,我們也把它劃歸RAII范疇。
但是,Matthew?Wilson在《Imperfect?C++》一書中,將其獨立出來,稱其為RRID(Resource?Release?Is?Destruction)。
RRID的實施需要在類的開發者和使用者之間建立契約,采用相同的方法獲取和釋放資源。比如,如果在shared_ptr構造時使用malloc(),便會出現問題,因為shared_ptr是通過delete釋放對象的。

轉載于:https://my.oschina.net/mskk/blog/3004171

總結

以上是生活随笔為你收集整理的C++ RAII的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。