對RAII資源管理的理解

2021-08-30 09:03:27 字數 1451 閱讀 1394

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...