使用C++11實現完美資源管理

qinfengxiaoyue發表於2014-04-16

1.資源管理包括記憶體管理、檔案控制程式碼等等需要進行開啟(申請)、關閉(釋放)操作的過程

2.VS2010使用的C++規範,嚴格說來不是C++11,而是C++0x,但是一脈相承的

一:管理陣列

相較於auto_ptr,unique_ptr的增強點之一是支援對陣列物件指標的管理,比如:

struct A
{
    int m_data;
    A(int n=0){m_data =n;cout<<n<<" 被構造了"<<endl;}
    ~A(){cout<<m_data<<" 被銷燬了"<<endl;}
    void Set(int n){m_data=n;
};

auto_ptr<A> p1(new A[5]);//由於自動釋放時,只呼叫delete,所以會導致A[0]以後物件的解構函式不會被呼叫。對於需要在解構函式中釋放資源的物件來說,是不能接受的。

unique_ptr<A[]> p2(new A[5]);//這樣,在釋放p2時,會使用delete [].

二:管理資源

在上一篇中,使用了sqlite:

sqlite3 *db = NULL;

//其他操作

sqlite3_close(db);

還有:

sqlite3_stmt *pstmt=NULL;

//其他操作

sqlite3_reset(pstmt);或者sqlite3_finalize(pstmt);

使用智慧指標或其他wrapper類管理資源,主要是
1.方便省事,最重要的是,避免資源洩露、未釋放

2.應對可能出現的異常.異常出現時,可以自動釋放資源,這就是所謂異常安全程式設計的三個條件之一(能釋放資源;能釋放資源且保證資源在異常前後狀態一致;不丟擲異常).另一方面,也可以使得程式碼美觀簡潔,否則為對付異常,不得不使用大堆大堆的if…else…

下面具體來看:

藉助於C++11(C++0x)新引入的auto、decltype、匿名函式物件(Lambda表示式)等特性,我們可以方便進行資源管理:

sqlite3 *pdb = NULL;

auto deleter = [](sqlite3 *pdb){sqlite3_close(pdb);}

int nRet =  sqlite3_open16(L"F:\\my.db",&db);

std::unique_ptr<sqlite3,decltype(deleter)> pdb(pdb,deleter);

if(nRet)

{//失敗,但是這裡不用擔心資源管理了

}

else

{

}

//其他操作

//結束前,會動釋放資源

這樣,其他的各類資源:User物件HWND,GDI物件HBRUSH,Kernel物件HANDLE等,都可以用此方法進行資源管理,凡此種種,可以自由發揮。哈哈,媽媽再也不用擔心我申請資源不釋放了!

下一篇,也許可以談談藉助於11裡面的bind和function,利用stratgy模式,實現虛擬函式的效果。(Effective C++有個Item談到了這種方法)

相關文章