raii是c++語言中常見習慣用法,全稱為「resource acquisition is initialization」意為資源獲取就是初始化。通常用來管理物件記憶體資源,已經比如檔案描述符、互斥鎖等資源。raii基本原理就是使用區域性物件管理資源,依賴於建構函式和析構函式的性質以及它們與異常處理的互動作用。我們考慮如下情況:
class a ; //某資源物件
a * create() ; //建立動態物件a 並返回指標
//考慮某處理函式f
void f()
沒錯這**看起來沒啥問題,但是考慮中間"....."部分加入一些控制流程語句如:if else 語句若其中包含return 語言,則必須在return語句返回之前都加上delete pimp;若分支語言很多則需要大量的delete語句。又例如:在"....."部分中包含其它函式呼叫導致異常發生,使得後面delete pimp 語句無法執行,從而導致記憶體洩漏。在這種情況下raii技術就非常適合!如下:
void f()
上述**create返回的資源被當做其管理者shared_ptr的初始值。不論控制流程如何離開區塊,在這之中若無發生shared_ptr物件拷貝、複製等(引用計數情況),一旦物件被銷毀(物件離開作用域)其析構函式自動會被呼叫,於是自動對其所指物件呼叫delete語句釋放資源。即使發生異常情況,我們依然無需多操心!
在考慮如下情況:
int go() //返回乙個處理引數
void processgo(std::shared_ptrpimp,int v); //處理過程
假如我們使用如下函式呼叫寫法:
void processgo(std::shared_ptr(new a),go());
**看起來也沒有啥問題,但是上述呼叫可能造成記憶體洩漏。分析如下:
呼叫函式processgo() 之前會做以下三件事:
1.呼叫go() 2.執行「new a」 3.呼叫shared_ptr建構函式。
c++ 編譯器 對於以上三件事會按照什麼次序完成呢?當然2、3 事件 ,一定是2事件優先於3事件。 但是1事件執行就比較任意了,若按照如下執行次序: 第一步: 執行new a 第二步:呼叫go() 第三步:呼叫 shared_ptr建構函式 。
萬一go函式的呼叫導致異常,在此情況下new a 返回的指標將會遺失,因為它尚未被置入shared_ptr內。從而發生洩漏。
避免這類問題發生也很簡單。就是寫成如下形式:
std::shared_ptrpimp(new a); //單獨語句內以智慧型指標儲存 new 物件
processgo(pimp,go()); //這樣就不至於造成洩漏
本文參考於effective c++ C 資源管理之 RAII
raii,它是 r esource acquisition is initialization 的首字母縮寫。也稱為 資源獲取就是初始化 是c 等程式語言常用的管理資源 避免記憶體洩露的方法。它保證在任何情況下,使用物件時先構造物件,最後析構物件。raii的好處在於它提供了一種資源自動管理的方式,當...
RAII慣用法 C 資源管理的利器
raii是指c 語言中的乙個慣用法 idiom 它是 resourceacquisitionisinitialization 的首字母縮寫。中文可將其翻譯為 資源獲取就是初始化 雖然從某種程度上說這個名稱並沒有體現出該慣性法的本質精神,但是作為標準c 資源管理的關鍵技術,raii早已在c 社群中深入...
RAII慣用法 C 資源管理的利器
原文 raii是指c 語言中的乙個慣用法 idiom 它是 resource acquisition is initialization 的首字母縮寫。中文可將其翻譯為 資源獲取就是初始化 雖然從某種程度上說這個名稱並沒有體現出該慣性法的本質精神,但是作為標準c 資源管理的關鍵技術,raii早已在c...