Учебное руководство RAII для [закрытого] C++

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

У кого-либо есть какие-либо хорошие ссылки, чтобы преподавать мне RAII?

34
задан Joe Bloggs 16 August 2013 в 15:33
поделиться

3 ответа

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

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

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

Указатели должны быть инкапсулированы в классы интеллектуальных указателей (см. Std :: auto_ptr, boost: : 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 -> WindowHandle :: WindowHandle -> :: Close (_window._value) ).

29
ответ дан 27 November 2019 в 17:10
поделиться

Объяснение википедии неплохое.

3
ответ дан 27 November 2019 в 17:10
поделиться

Самая полезная ссылка на тему RAII - это книга Exceptional C ++ Херба Саттера.

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

2
ответ дан 27 November 2019 в 17:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: