在C++函数中优雅的处理资源释放
在审查代码的过程中发现如下代码:
conf_t cdConf = conf_new();
if (cdConf == NULL)
{
return -1;
}
if (conf_load(au.get(), CLUSTERD_CONF) == 0)
{
conf_delete(cdConf);
return -1;
}
if (xxxxxxx)
{
conf_delete(cdConf);
return -1;
}
conf_delete(cdConf);
return 0;
在每个错误分支的处理都需要释放资源,假如分支特别多那就很容易遗漏。
特别是以后代码进行维护的时候。有没有一种办法可以实现资源的自动析构呢?
其实C++中的RAII机制就可以实现该功能。将资源的生命周期交给某个局部变量
管理,随栈执行完局部变量的释放而释放。Auto_ptr是这个机制的典型代表,但是对于这种是基于c函数接口,auto_ptr无法使用。除非专门针对这种资源编写C++类。其实只要我们将资源的析构函数指针移植进行,也可以实现类似auto_ptr功能。代码如下:
template <typename T>
class auto_fptr
{
public:
typedef void (*FP)(T*);
auto_fptr(T* p = NULL, FP pF = NULL) :
m_pValue(p),
m_pFunc(pF)
{
}
~auto_fptr()
{
m_pFunc(m_pValue);
}
T* get()const
{
return m_pValue;
}
T* operator -> () const
{
return m_pValue;
}
T& operator * () const
{
return *m_pValue;
}
protected:
template <typename U> auto_fptr& operator = (const auto_fptr<U>& tf);
auto_fptr& operator = (const auto_fptr& tf);
template <typename U> auto_fptr(auto_fptr<U>& tf);
auto_fptr(const auto_fptr<T>& tf);
private:
T* m_pValue;
FP m_pFunc;
};
当然,这个模板类只能处理,资源以指针形式存在,且析构函数为void类型,参数为资源指针的形式。应该可以处理绝大多数C形式的资源释放问题。
特殊情况可以利用模板的特化性质进行处理,
比如上例中的conf_t, 其实是一个void*指针,所以模板特化处理如下:
template <>
class auto_fptr<conf_t>
{
public:
auto_fptr(conf_t value) :
m_value(value)
{
}
~auto_fptr()
{
conf_delete(m_value);
}
conf_t get() const
{
return m_value;
}
protected:
auto_fptr& operator = (const auto_fptr<conf_t>& tf);
auto_fptr(const auto_fptr<conf_t>& tf);
private:
conf_t m_value;
};