条款14 在资源管理类中小心coping行为
例如我们现在要处理一个Mutex互斥的对象,有lock和unlock使用。
void lock(Mutex* pm);
void unlock(Mutex* pm);
然后建立一个class用来管理锁。
class Lock
{
public:
explicit Lock(Mutex* pm):mutexPtr(pm)
{
lock(mutexPtr);//获取资源
}
~Lock()
{
unlock(mutexPtr)//释放资源
}
private:
Mutex mutexPtr;
我们这样就可以放心使用Lock了。
现在的问题是当我们Lock对象被复制会发生什么。
Lock m1(&m);
Lock m2 = m1;
我们有两种或者更多其他选择:
禁止复制
class Lock : private Uncopyable{};使用引用计数法
我们可以使用tr1::shared_ptr< Mutex >但是引用次数为0它将删除Mutex,而我们需要的是解除锁定。
幸运的是shared_ptr可以指定“删除器”也就是引用次数为0时被调用。
class Lock
{
//指定删除器为 unlock
explicit Lock(Mutex* pm):mutexPtr(pm,unlock)
{
lock(mutexPtr);
}
private:
std::tr1::shared_ptr<Mutex> mutexPtr;
}
这样就不需要声明析构函数了。
实现一个仿函数
其实那个删除器的名字又称为仿函数。
仿函数是什么?
不是函数但可以像函数一样使用,因为重载了operator()
例如
//定制仿函数
template<class T>
struct Less
{
//T类型必须实现了operator<运算符
bool operator()(const T& l, const T& r)
{
return l < r;
}
};
下面我们实现一个带有删除器的智能指针
template<class T>//注意这里有模版 默认new申请内存释放
struct Del
{
void operator()(const T* ptr)
{
delete ptr;
}
};
struct Free//注意这里没有模版 对应malloc申请内存
{
void operator()(void* ptr)
{
free(ptr);
}
};
//带有默认删除器 Del
template<class T, class Deleter = Del<T>>
class SharedPtr
{
public:
SharedPtr(T* ptr, Deleter del) :
m_ptr(ptr),
m_count(new long(1)),
m_del(del) {}
SharedPtr(T* ptr):
m_ptr(ptr),
m_count(new long(1)) {}
~SharedPtr()
{
release();
}
protected:
void release()
{
if(--*m_count == 0)
{
m_del(m_ptr);
delete m_count;
m_count = nullptr;
cout <<"del"<<endl;
}
}
private:
T* m_ptr;
long* m_count;
Deleter m_del;
};
void test()
{
SharedPtr<int>sp1(new int(1));
SharedPtr<int,Free>sp2((int*)malloc(sizeof(int) * 10), Free());//注意怎么调用的
}
完成!