Если вам нужен доступ к нестатическим элементам из Close
, вам необходимо правильно связать его аргумент this
CWrapper() :
m_pHandle(new HANDLE, boost::bind(&CWrapper::Close, this, _1)) {
//code to open handle
}
Это, однако, содержит скрытую ошибку . Ваш объект является копируемым, и вы привязываете средство удаления к объекту *this
. Дескриптор связан с первой созданной вами оболочкой, но если вы копируете оболочку, дескриптор используется совместно, но связывается с первой оболочкой, которая может больше не существовать:
CWrapper getWrapper() { CWrapper w; return w; }
CWrapper x = getWrapper();
После того, как этот код был выполнен и x
будет уничтожен, поведение не определено, потому что уничтожение x
внутреннего указателя дескриптора попытается использовать объект, связанный в вызове конструктора w
- однако этот объект больше не существует!
Решением этой проблемы может быть сохранение данных, связанных с дескриптором, в самом выделенном объекте, вместо попытки сохранить их в объекте дескриптора верхнего уровня, как в следующем коде
class CWrapper
{
public:
CWrapper():m_pHandle(new CHandle)
{ }
private:
// This class cannot be copied
class CHandle : boost::noncopyable {
friend class CWrapper;
CHandle()
:m_pHandle(new HANDLE) {
// code to open handle
}
~CHandle() {
// code to close this handle, making use of
// auxilary data for whatever reason
}
private:
boost::scoped_ptr<HANDLE> m_pHandle;
// auxilary data associated with the handle...
};
boost::shared_ptr<CHandle> m_pHandle;
};
Вспомогательные данные больше не хранятся в дескрипторе, но вместе с данными, которые совместно используются всеми копиями оболочки. Совместно используемые данные создаются и уничтожаются с помощью обычного конструктора и деструктора.
CWrapper getHandle() { return myHandle; }
CWrapper w = getHandle();
Последняя обертка, выходящая из жизни, уничтожит дескриптор, который явно используется всеми обертками.