2010-04-14 74 views
29

我想了解如何在C++中使用RAII。我想我知道它是什麼,但不知道如何在我的程序中實現它。快速谷歌搜索沒有顯示任何漂亮的教程。C++的RAII教程

有沒有人有任何不錯的鏈接教我RAII?

+5

不是外部鏈接,但你可以在這裏找到一些很好的答案:http://stackoverflow.com/questions/395123/raii-and-smart-pointers-in-c – Naveen 2010-04-14 08:28:13

+0

@Naveen - 謝謝,那個沒有當我在我的標題中輸入時顯示在我的鏈接中 – 2010-04-14 08:29:01

+1

@Joe Bloggs:我使用谷歌網站:stackoverflow.com。它產生更好的結果。 – Naveen 2010-04-14 08:30:06

回答

23

沒有什麼(也就是說,我不認爲你需要一個完整的教程)。

RAII可以簡短地解釋爲「每個需要清理的資源都應該被賦予一個對象的構造函數。」

換句話說:

指針應在智能指針類被封裝(見的std :: auto_ptr的,升壓:: shared_ptr的和boost :: scoped_ptr的例子)。

需要清理的句柄應該封裝在銷燬時自動釋放/釋放句柄的類中。

同步應該依賴在範圍退出時釋放互斥/同步原語(參見boost :: mutex :: scoped_lock用法舉例)。

我不認爲你真的可以有一個關於RAII的教程(不再比你可以有一個關於設計模式的例子)。 RAII更像是一種查看資源的方式。

例如,在現階段,我使用WinAPI的我編碼和我寫了下面的類:

template<typename H, BOOL _stdcall CloseFunction(H)> 
class checked_handle 
{ 
public: 
    typedef checked_handle<H,CloseFunction> MyType; 
    typedef typename H HandleType; 

    static const HandleType  NoValue; 

    checked_handle(const HandleType value) 
     : _value(value) 
    { 
    } 

    ~checked_handle() 
    { 
     Close(); 
    } 

    HandleType* operator &() 
    { 
     return &_value; 
    } 

    operator HandleType() 
    { 
     return _value; 
    } 

private: 
    HandleType  _value; 

    void Close(const HandleType newValue = NoValue) 
    { 
     CloseFunction(_value); 
     _value = newValue; 
    } 
}; 

template<typename H,BOOL _stdcall CloseFunction(H)> 
const typename checked_handle<H,CloseFunction>::HandleType 
    checked_handle<H,CloseFunction>::NoValue = 
    checked_handle<H,CloseFunction>::HandleType(INVALID_HANDLE_VALUE); 

typedef checked_handle<HANDLE,::CloseHandle> CheckedHandle; 
typedef checked_handle<HWINSTA,::CloseWindowStation> WinStationHandle; 
typedef checked_handle<HDESK,::CloseDesktop> DesktopHandle; 
typedef checked_handle<HDEVNOTIFY,::UnregisterDeviceNotification> DevNotifyHandle; 
typedef checked_handle<HWND,::DestroyWindow> WindowHandle; 

BOOL __stdcall CloseKey(HKEY hKey); 
typedef checked_handle<HKEY,CloseKey> RegHandle; 

本類不包括分配和複製語義(我刪除他們提供一個最小的例子)所以按值返回,會導致手柄關閉兩次。

這裏是如何使用它:

類聲明:

class Something 
{ 
public: 
    // ... 
private: 
    WindowHandle  _window; 
}; 

該成員分配,但我從來沒有叫::CloseWindow(_window._handle)明確地(當Something實例走出去的範圍將被調用(如Something::~Something - >WindowHandle::WindowHandle - >::Close(_window._value))。

+3

這也可以使用boost :: shared_ptr與自定義釋放器完成。例如,'boost :: shared_ptr checked_handle(open_some_handle(),boost :: bind < void >(&:: CloseHandle,_1));' – 2010-04-14 21:40:05

+1

好點,但我至少會用一些typedef-ing來寫。我不喜歡用一個名爲「shared_ptr」的類來做別的東西,而不是指針。 它導致維修中的道路混亂。 – utnapistim 2010-04-26 15:12:13

+0

從某種意義上說,句柄是一個指針。它是使用原始數據類型的一些資源的表示(即它通常指向使用整數的資源)。 – 2013-08-16 15:50:03

2

我個人發現對RAII主題最有幫助的參考書是Herb Sutter的書Exceptional C++

這本書中涵蓋的許多主題在Sutter的每週一文中都有涉及。這些文章可從http://gotw.ca/gotw/index.htm獲得。

+2

Exceptional C++的哪一章涵蓋了RAII的主題? – Javier 2011-02-17 14:57:16