C++ HDF5函数和智能析构函数-std::unique_ptr()
许多HDF5函数的初始化如下C++ HDF5函数和智能析构函数-std::unique_ptr(),c++,smart-pointers,hdf5,hdf,C++,Smart Pointers,Hdf5,Hdf,许多HDF5函数的初始化如下 hid_t handler = DoSomething(someHandler); 用户必须手动释放此类操作保留的内存,方法如下: freeme(handler); 因此,使用malloc和/或new操作符也会带来同样的噩梦/问题 我想创建一些类似于unique\u ptr的东西来在销毁时处理这个问题但是,问题是每个不同的函数都有不同的释放函数 例如: hid_t attribType = H5Aget_type(attribHandler); 必须以自由的方
hid_t handler = DoSomething(someHandler);
用户必须手动释放此类操作保留的内存,方法如下:
freeme(handler);
因此,使用malloc
和/或new
操作符也会带来同样的噩梦/问题
我想创建一些类似于unique\u ptr
的东西来在销毁时处理这个问题但是,问题是每个不同的函数都有不同的释放函数
例如:
hid_t attribType = H5Aget_type(attribHandler);
必须以自由的方式释放
H5Tclose(attribType);
H5Aclose(attribHandler);
但是这个函数
attribHandler = H5Aopen(obj_id,"name",H5P_DEFAULT);
必须以自由的方式释放
H5Tclose(attribType);
H5Aclose(attribHandler);
因此,我需要编写一个类,它可以将hid\u t
作为模板参数(这很简单),也可以将释放函数作为某种参数,并在销毁时调用它
实现这一目标的最佳方式是什么
更新 有人建议我对自定义删除程序使用
std::unique_ptr
,但这不起作用,因为std::unique_ptr
需要一个指针
std::unique_ptr<hid_t,std::function<herr_t(hid_t)>> attribType(H5Aget_type(attribHandler), [](hid_t f) { return H5Tclose(f); });
std::unique_ptr attribType(H5Aget_type(attribHandler),[](hid_t f){返回H5Tclose(f);});
由于第二个参数lambda函数,这将创建一个编译错误。错误显示为(g++4.9):
错误:从'hid_t{aka int}'到'std::unique_ptr::pointer{aka int*}'[-fppermissive]的转换无效
std::unique_ptr attribType(H5Aget_type(attribHandler),[](hid_t f){return H5Tclose(f);});
^
发生此错误的原因是std::unique_ptr
希望保留指向hid_t
的指针,而不是hid_t
对象
有办法解决这个问题吗?我想我现在可以编写自己的类来实现这一点(我可以使用std::function来回答我的第一个问题),但如果我可以使用
std::unique\u ptr
以下内容可能会更好:
struct MyDeleter {
typedef hid_t pointer;
typedef void (*FreeFunc)(hid_t);
FreeFunc free_func_;
MyDeleter(FreeFunc free_func) : free_func_(free_func) {}
void operator()(hid_t f) const { free_func_(f); }
};
std::unique_ptr<hid_t, MyDeleter> p(
H5Aget_type(attribHandler),
MyDeleter(H5Tclose));
struct MyDeleter{
typedef隐藏指针;
typedef void(*FreeFunc)(隐藏);
自由函数\u func;
MyDeleter(FreeFunc free_func):free_func(free_func){}
void运算符()(hid_t f)const{free_func_(f);}
};
std::唯一的\u ptr p(
H5Aget_类型(属性处理程序),
MyDeleter(H5Tclose));
我创建了自己的处理程序类。。。事实证明,这并不难:
template <typename T, typename Deleter>
class SmartHandle
{
public:
typedef T value_type;
typedef Deleter deleter_function;
private:
T _value;
Deleter _deleter;
public:
SmartHandle(T value, Deleter deleter);
~SmartHandle();
T get();
};
template <typename T, typename Deleter>
SmartHandle<T,Deleter>::SmartHandle(T value, Deleter deleter)
{
this->_value = value;
this->_deleter = deleter;
}
template <typename T, typename Deleter>
T SmartHandle<T,Deleter>::get()
{
return _value;
}
template <typename T, typename Deleter>
SmartHandle<T,Deleter>::~SmartHandle()
{
_deleter(_value);
}
模板
类智能句柄
{
公众:
类型定义T值_类型;
typedef Deleter Deleter_函数;
私人:
T_值;
Deleter _Deleter;
公众:
智能手柄(T值,删除器删除器);
~SmartHandle();
T get();
};
模板
SmartHandle::SmartHandle(T值,Deleter-Deleter)
{
此->\u值=值;
此->\u deleter=deleter;
}
模板
T SmartHandle::get()
{
返回_值;
}
模板
SmartHandle::~SmartHandle()
{
_删除器(_值);
}
要使用它:
SmartHandle<hid_t,std::function<herr_t(hid_t)>> attribType(H5Aget_type(attribHandler.get()), [](hid_t f) { return H5Tclose(f); });
SmartHandle属性类型(H5Aget_类型(attribHandler.get()),[](hid_t f){return H5Tclose(f);});
这里的
attribHandler
也使用了SmartHandle
,这就是为什么那里有一个.get()
。您可以使用类似于:
template <typename Factory, Factory factory,
typename Deleter, Deleter deleter>
class SmartHandleH5;
template <typename Ret, typename ... Ts, Ret (*factory)(Ts...),
void (*deleter)(Ret)>
class SmartHandleH5<Ret (*)(Ts...), factory, void (*)(Ret), deleter>
{
public:
template <typename ... Us>
SmartHandle(Us&&... args) : handler(factory(std::forward<Us>(args)...)) {}
// Not copyable
SmartHandle(const SmartHandle&) = delete;
SmartHandle& operator =(const SmartHandle&) = delete;
// Not movable
SmartHandle(SmartHandle&&) = delete;
SmartHandle& operator =(SmartHandle&&) = delete;
// To avoid strange case with our template constructor
SmartHandle(SmartHandle&) = delete;
SmartHandle(const SmartHandle&&) = delete;
~SmartHandle() { deleter(handler); }
const T& get() const { return handler; }
T& get() { return handler; }
private:
Ret handler;
};
此外,您可能需要添加一个额外的层来完全隐藏hid\u t
template <typename SmartHandle>
class HidHandle : private SmartHandle
{
public:
using SmartHandle::SmartHandle;
void foo() { someFunctionUsingHid(get()); }
};
模板
类HidHandle:私有SmartHandle
{
公众:
使用SmartHandle::SmartHandle;
void foo(){someFunctionUsingHid(get());}
};
及
使用HidHandleGetType=HidHandle;
使用HidHandleOpen=HidHandle;
std::unique\u ptr
将删除器作为额外的模板参数std::shared_ptr
将删除器作为可选的额外构造函数参数。@IgorTandetnik噢!让我试试@IgorTandetnik请检查更新。“std::unique\u ptr
需要一个指针”Falsestd::unique_ptr
与Deleter::pointer
一起使用,它可能是T*
。您需要投入更多的工作来创建一个合适的自定义删除程序。谢谢。。。但是我不得不说,编写自己的类要比这简单得多。其实我已经这么做了,因为我觉得你永远不会回应+1感谢您的帮助:-)您忘记删除复制构造函数和赋值(规则3)。@Jarod42您完全正确。这太快了,太脏了:)非常感谢你解决了这个问题(+1)。虽然您的解决方案非常完美,但我不喜欢使用多行来调用单个句柄。
template <typename SmartHandle>
class HidHandle : private SmartHandle
{
public:
using SmartHandle::SmartHandle;
void foo() { someFunctionUsingHid(get()); }
};
using HidHandleGetType = HidHandle<SmartHandlerGetType>;
using HidHandleOpen = HidHandle<SmartHandlerOpen>;