Постепенно мигрирую с C на C++ и 32- на 64-битную Windows. При написании программ с использованием WinAPI возник ряд вопросов, объединенных одной общей темой - RAII. Так как я изучаю C++ всего третий месяц, а понять некоторые тонкости вышеозвученной идиомы программирования все же хотелось уже сейчас (хотя бы на базовом уровне), решила задать вопрос знающим в том людям. Как выглядит в моем представлении шаблон RAII для большинства API функций (с учетом 64-битных версий Windows)?
// обращаться к функциям освобождения ресурсов по адресу
typedef VOID (WINAPI *PFNCLEANUP)(UINT_PTR);
template<class T, PFNCLEANUP pfn, UINT_PTR inval = NULL>
class CResFree {
private:
UINT_PTR m_res;
public:
CResFree() { m_res = inval; } // конструктор по умолчанию
// этот конструктор задает значение
CResFree(T t) : m_res(reinterpret_cast<UINT_PTR>(t)) {}
// здесь реализуется логика освобождения ресурсов
~CResFree() { Cleanup(); }
// вспомогательная функция класса, позволяет установить
// является ли ресурс валидным или нет
BOOL IsValid() const { return (m_res != inval); }
// если нужно переназначить данные нашего ресурса
T operator=(T t) {
Cleanup(); // освободили ресурс
m_res = reinterpret_cast<UINT_PTR>(t); // задали новое значение
return (*this); // вернули данные
}
// вернуть значение
operator T() { return reinterpret_cast<T>(m_res); }
// собственно функция очистки
void Cleanup() {
if (IsValid()) {
pfn(m_res); // освободили ресурс
m_res = inval; // потерли данные
}
}
};
Код я достаточно плотно закомментировала, так что если я в чем-то неправа, матерые кодеры C++ мне сразу укажут на ошибки. В чем состоит мой вопрос? Прежде всего насколько корректно мое представление о RAII? На мой взгляд все достаточно логично и каких-либо дополнительных перегрузок или еще чего-то не требуется. Но, повторюсь, это только на мой взгляд. Хотелось бы конструктивной критики. Также у меня есть вопрос как упростить объявление типа в последствии, так как на данный момент эти объявления относительно кода выше у меня выглядят так:
typedef CResFree<HANDLE, reinterpret_cast<PFNCLEANUP>(CloseHandle), reinterpret_cast<UINT_PTR>(INVALID_HANDLE_VALUE)> CCloseFile;
В C можно использовать макросы, но мне часто доводилось слышать что макросы в C++ использовать не стоит, лучше использовать встраиваемые (inline) функции. Однако встраиваемые функции жрут память как не в себя. Может тогда есть более лучший вариант RAII вообще, скажем, через лямбда?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Можно ли как-то отключить сортировку по ключи в контейнере типа map? Допустим, есть код:
Недавно нашел интереснейшую задачуОчень хочу ее решить, но нет никаких идей (кроме как условиями)
Задача: преобразовать a/b в сумму чисел вида 1/nНапример, когда a=3 и b=7, то программа должна вывести 3/7 = 1/3 + 1/11 + 1/231