Effective C++ 14:资源管理类要特别注意拷贝行为

Item 14: Think carefully about copying behavior in resource-managing classes.

Item 13:使用对象来管理资源中提出了基于RAII的资源管理对象auto_ptrshared_ptr。 智能指针可以有不同的拷贝策略。当你实现这样一个资源管理对象时,需要特别注意。比如一个典型的RAII风格的互斥锁实现:

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

explicit限定构造函数,可以防止隐式转换的发生:Lock l = pm

该互斥锁的使用方式很简单,只需要为每个临界区创建一个C++代码块,在其中定义Lock的局部变量:

Mutex m;            // 定义互斥锁
{                   // 创建代码块,来定义一个临界区
    Lock m1(&m);    // 互斥锁加锁
    ...             // 临界区操作
}                   // m1退出作用域时被析构,互斥锁自动解锁

m1被复制时情况会怎样?把当前作用域的代码加入到同一个临界区中?拷贝互斥锁并定义一个新的临界区?还是简单地给互斥锁换一个资源管理者? 资源管理对象的拷贝行为取决于资源本身的拷贝行为,同时资源管理对象也可以根据业务需要来决定自己的拷贝行为。可选的拷贝行为不外乎下面这四种:

  1. 禁止拷贝。简单地私有继承一个Uncopyable类便可以让它禁止拷贝。参见:Item 6:禁用那些不需要的缺省方法
  2. 引用计数,采用shared_ptr的逻辑。恰好shared_ptr构造函数提供了第二个参数deleter,当引用计数到0时被调用。所以Lock可以通过聚合一个shared_ptr成员来实现引用计数:
 class Lock{
 public: 
     explicit Lock(Mutex *pm): mutexPtr(pm, unlock){
         lock(mutexPtr.get());
     }
     private: 
         std::shared_ptr<Mutex> mutexPtr;
     }
     // `Lock`的析构会引起`mutexPtr`的析构,而`mutexPtr`计数到0时`unlock(mutexPtr.get())`会被调用。
 };
  1. 拷贝底层资源。当你可以任意拥有底层资源时,可以直接拷贝它。比如string的行为:内存存有指向堆空间的指针,当它被复制时会复制那片空间。
  2. 转移底层资源的所有权。auto_ptr就是这样做的,把资源移交给另一个资源管理对象,自己的资源置空。

本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2015/08/04/effective-cpp-14.html。如有疏漏、谬误、侵权请通过评论或 邮件 指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值