Подтвердить что ты не робот

Учебник RAII для С++

Я хотел бы узнать, как использовать RAII в С++. Я думаю, что знаю, что это такое, но не знаю, как реализовать его в моих программах. Быстрый поиск в Google не показывал никаких хороших уроков.

Есть ли у кого-нибудь хорошие ссылки, чтобы научить меня RAII?

4b9b3361

Ответ 1

Там ничего нет (то есть, я не думаю, что вам нужен полный учебник).

RAII можно коротко объяснить следующим образом: "Каждый ресурс, требующий очистки, должен быть предоставлен конструктору объекта".

Другими словами:

Указатели должны быть инкапсулированы в классы интеллектуального указателя (например, std:: auto_ptr, boost:: shared_ptr и boost:: scoped_ptr).

Ручки, требующие очистки, должны быть инкапсулированы в классы, которые автоматически освобождают/освобождают дескрипторы при уничтожении.

Синхронизация должна полагаться на освобождение примитива mutex/synchronization при выходе из области действия (см. пример 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::~SomethingWindowHandle::WindowHandle::Close(_window._value)).

Ответ 2

Описание wikipedia не плохо.

Ответ 3

Ссылка, которую я лично нашел наиболее полезной по теме RAII, - это книга Исключительный С++ от Herb Sutter.

Многие из тем, затронутых в этой книге, затрагиваются в статьях Учителя недели Саттера. Эти статьи доступны в http://gotw.ca/gotw/index.htm.