effective C++ 条款 14:资源管理类中小心copying行为

并非所有的资源都是heap-based,对那种资源来讲,auto_ptr和shared_ptr这样的智能指针往往不适合作为资源掌管着。你可能需要

自己建立自己的资源管理类。

例如,处理类型为Mutex的互斥器对象,有lock和unlock两函数可用。

void lock(Mutex* pm);
void unlock(Mutex* pm);
class Lock{
public:
    explicit Lock(Mutex* pm)
        : mutexPtr(pm);
    {
        lock(mutexPtr); //获得资源
    }
    ~Lock(){unlock(mutexPtr);} //释放资源
private:
    Mutex *mutexPtr;
};

当一个RAII对象被复制,会发生什么事?大多数会选择下面两种可能:

 

    1. 禁止复制。许多时候允许RAII对象复制并不合理。Lock看起来是这样:
    2. class Lock:private Uncopy{ //禁止复制,见条款6

      };

    3. 对底层资源祭出“引用计数法”(reference counting)。有时候我们希望保有资源,直到它的最后一个使用者(某对象)被销毁
    4. 通常只要引用一个tr1::shared_ptr成员变量便可实现出reference_counting copy行为,但此时,tr1::shared_ptr的缺省行为是“当引用次数为0时删除其所指物”,那不是我们所要的行为。幸运的是,tr1::shared_ptr允许我们指定所谓的“删除器”(deleter),当引用次数为0时被调用,(此机能并不存在于auto_ptr)。删除器对tr1::share_ptr构造函数而言是可有可无的第二个参数:

      void lock(Mutex* pm);
      void unlock(Mutex* pm);
      class Lock{
      public:
      explicit Lock(Mutex* pm)
      : mutexPtr(pm, unlock);//以某个Mutex初始化shared_ptr,并以unlock函数为删除器
      {
      lock(mutexPtr.get());
      }
      ~Lock(){unlock(mutexPtr);}
      private:
      std::tr1::shared_ptr<Mutex> mutexPtr;
      };

      本例Lock class不再声明析构函数。class析构函数(不论是编译器自动生成的,还是用户定义的)会自动调用其non-static成员变量(本例mutexPtr)的析构函数。mutexPtr的析构函数会在互斥器的引用次数为0时自动调用tr1::shared_ptr的删除其器(本例为unlock)

    5. 复制底部资源。可以对一份资源拥有其任意数量的复件。复制资源管理对象时是“深度拷贝”。
    6. 标准字符串类型是由指向heap内存的指针构成,当这样一个字符串对象被复制,不论指针还是其所指内存都会被复制一个复件。这样的字符串展现“深度复制”。

    7. 转移底部资源的拥有权。你希望确保只有一个RAII对象指向一个未加工资源,即使RAII被复制依然如此。资源的拥有权从被复制转移到目标物。auto_ptr的复制意义。

复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为

posted @ 2012-01-14 21:22  lidan  阅读(346)  评论(0编辑  收藏  举报