Я хотел бы изучить, как использовать RAII в C++. Я думаю, что знаю, каково это, но понятия не имейте, как реализовать его в моих программах. Быстрый поиск Google не показал хороших учебных руководств.
У кого-либо есть какие-либо хорошие ссылки, чтобы преподавать мне RAII?
В этом нет ничего особенного (то есть я не думаю, что вам нужно полное руководство).
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)
).
Самая полезная ссылка на тему RAII - это книга Exceptional C ++ Херба Саттера.
Многие темы, затронутые в этой книге, затронуты в статьях Саттера «Гуру недели». Эти статьи доступны на http://gotw.ca/gotw/index.htm .