条款14:在资源管理中心小心copy行为之重难点

来源:互联网 发布:淘宝刷手被发现 编辑:程序博客网 时间:2024/06/07 11:32

不仅仅动态分配的内存是资源,像文件描述器,互斥锁,数据库连接,以及网络sockets等也是资源,如果不及时关闭,也会造成资源浪费。

重点1:建立自己的资源管理类

如果是heap-based资源,则可以用auto_ptr或shared_ptr管理资源。然而并非所有资源都是heap-based,这样,就需要建立自己的资源管理类。

以互斥锁为例,为确保不会忘记将一个被锁住的mutex解锁,我们希望建立一个class来管理机锁。这样的class的基本结构由RAII守则支配,也就是“资源在构造期间获得,在析构期间释放”:

class Lock{public:  explicit Lock(Mutex* pm):mutexPtr(pm)  {    lock(mutexPtr);  }  ~Lock()  {    unlock(mutexPtr);  }private:  Mutex *mutexPtr;};


客户对Lock的用法符合RAII方式:

Mutex m;...{  Lock m1(&m);  ...}
难点1:RAII class copying行为
如果上面Lock对象被复制,会发生什么事?

Lock m11(&m);        //锁定m                                                  Lock m12(&m11);       //将m11复制到m12身上 

这是一个一般化问题的特定例子:当一个RAII 对象被复制,会发生什么事?大多时候,选择下面两种可能:

1)禁止复制。

class Uncopyable{protected:              //允许继承对象构造和析构                              Uncopyable(){}  ~Uncopyable(){}private:  Uncopyable(const Uncopyable &);     //但阻止copy                                Uncopyable &operator=(const Uncopyable&);};
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">为阻止Lock对象被复制,我们唯一需要做的就是继承Uncopyable:</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp">class Lock:private Uncopyable{public:  ...};


2)对底层资源祭出“引用计数法”。

有时候我们希望保有资源,直到它的最后一个使用者被销毁。这个时候使用tr1::shared_ptr来引用计数。但是tr1::shared_ptr的缺省行为是“当引用次数为0时”删除其所指物,那不是我们的行为。当我们用上Mutex,我们想要做的释放动作是解锁而不是删除。

这可以给tr1::shared_ptr指定删除器来实现:

class Lock{public:  explicit Lock(Mutex* pm):mutexPtr(pm,unlock)  //unlock为指定的删除器          {    lock(mutexPtr.get());                   //get为显示转换函数             }private:  std::tr1::shared_ptr<Mutex> mutexPtr;        //使用shared_ptr代替原始指针  };
注意1:shared_ptr有两个参数,第一个是类型,第二个指定删除器,一般是函数,第二个参数可以省略,表示默认是删除对象。

注意2:本例的Lock class不再声明析构函数。class析构函数会自动调用其non-static成员变量的析构函数。

0 0
原创粉丝点击