There's nothing to it (that is, I don't think you need a full tutorial).
RAII can be shortly explained as "Every resource requiring cleanup should be given to an object's constructor."
In other words:
Pointers should be encapsulated in smart pointer classes (see std::auto_ptr, boost::shared_ptr and boost::scoped_ptr for examples).
Handles requiring cleanup should be encapsulated in classes that automatically free/release the handles upon destruction.
Synchronization should rely on releasing the mutex/synchronization primitive upon scope exit (see boost::mutex::scoped_lock usage for an example).
I don't think you can really have a tutorial on RAII (not anymore than you can have one on design patterns for example). RAII is more of a way of looking at resources than anything else.
For example, at the moment I'm coding using WinAPI and I wrote the following class:
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;
This class doesn't include assignment and copy semantics (I removed them to provide a minimal example) so returning by value, will cause the handles to be closed twice.
Here's how it's used:
class declaration:
class Something
{
public:
// ...
private:
WindowHandle _window;
};
This member is allocated but I never call ::CloseWindow(_window._handle)
explicitely (it will be called when instances of Something
go out of scope (as Something::~Something
-> WindowHandle::WindowHandle
-> ::Close(_window._value)
).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…