C++箴言:谨慎考虑资源管理类的拷贝行为

C++箴言:谨慎考虑资源管理类的拷贝行为,第1张

C++箴言:谨慎考虑资源管理类的拷贝行为,第2张

在上一篇文章中,介绍了资源管理的支柱资源获取即初始化(RAII)的原理,并描述了auto_ptr和tr1::shared_ptr将该原理应用于基于堆的资源的性能。并非所有的资源都是基于堆的,然而,对于这样的资源,像auto_ptr和tr1::shared_ptr这样的智能指针通常不像资源处理程序那样合适。在这种情况下,有时,您可能希望根据自己的需要创建自己的资源管理类。

例如,假设您使用C API提供的锁定和解锁函数来操作互斥类型互斥对象:

void lock(互斥* pm);//锁定pm指向的互斥体

void解锁(互斥* pm);//解锁互斥体

为了确保您永远不会忘记解锁已经锁定的互斥体,您需要创建一个类来管理锁。RAII原则规定了这样一个类的基本结构,它通过构造函数获取资源,通过析构函数释放资源:

class Lock {
public:
explicit Lock(Mutex * pm)
:Mutex ptr(pm)
{ Lock(Mutex ptr);} //获取资源

~ Lock(){ unlock(mutexPtr);} //释放资源

private:
Mutex * Mutex ptr;
};

根据RAII风格的习惯使用锁:

互斥m;//定义需要使用的互斥锁
...
{ //创建块来定义临界区
Lock ml(& m);//锁定互斥锁
...//执行临界区操作

} //在块的结尾
//自动解锁互斥体

这没有错,但是如果复制了一个锁对象应该怎么办呢?

锁定ml1(& m);//锁定m

锁定ml2(ml1);//将ml1复制到ml2——这里应该会发生
//什么情况?

这是一个更普遍问题的具体例子。每一个RAII类的作者都要面对这个问题:当一个RAII对象被复制的时候会发生什么?在大多数情况下,您可以选择以下可能性之一:

禁止复制。很多时候,允许RAII被复制是没有意义的。对于像Lock这样的类来说,这可能是正确的,因为同步的基本元素的“副本”没有什么意义。当复制对RAII类没有任何意义时,你应该禁止它。第6项解释了如何做到这一点。将复制操作声明为私有。对于锁,它可能看起来像这样:

类锁:私有不可复制{ //禁止复制-请参见
public: // Item 6
...//和以前一样
};

对底层的资源引用计数。有时候人们需要的是保留一个资源,直到最后一个使用它的对象被销毁。在这种情况下,复制RAII对象应该会增加引用该资源的对象的数量。这就是使用tr1::shared_ptr时“复制”的意思。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » C++箴言:谨慎考虑资源管理类的拷贝行为

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情