Search code examples
c++raii

RAII tutorial for C++


I'd like to learn how to use RAII in c++. I think I know what it is, but have no idea how to implement it in my programs. A quick google search did not show any nice tutorials.

Does any one have any nice links to teach me RAII?


Solution

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