【复读EffectiveC++14】条款14:在资源管理类中小心拷贝行为

本文讨论了在资源管理中避免死锁问题的两种方法:一是通过声明私有复制或设计不可复制类,二是采用引用计数法,如shared_ptr,当引用计数为0时解锁资源。RAII对象的复制行为与其管理的资源密切相关。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

条款14:在资源管理类中小心拷贝行为

此条款,针对对象管理资源的补充,内容分为两个部分:

  • 为什么小心拷贝行为
  • 怎么解决

一、为什么小心拷贝行为

解释为什么,原书直接给了一个有关死锁的例子:

void lock(Mutex* pm);   //锁定pm所指的互斥器
void unlock(Mutex* pm); //将互斥器解锁
class Lock
{
public:
    //获得资源
    explicit Lock(Mutex* pm) :mutexPtr(pm) {
        lock(mutexPtr);
    }

    //释放资源
    ~Lock() { unlock(mutexPtr); }
private:
    Mutex *mutexPtr;
};
Mutex m;

void f()
{
    Lock m1(&m);//管理Mutex对象
    //...
    
    Lock m2(m1); //拷贝

}//函数结束后,自动调用ml的析构函数解锁

因为m2拷贝时会调用lock函数对Mutex对象进行加锁,但是m对象此时处于使用状态,因为其会阻塞等待,等待m1释放互斥量,但是m1此时也无法向下执行,因此这个程序就产生死锁了

所以对于Lock这个类,是不希望有拷贝行为的。

二、怎么解决

1、禁止复制

(1)将 copying 操作声明为 private
(2)或者设计一个不可以被复制的类

class Toby: private UncopyToby{
public...
}

2、对底层资源使用 “引用计数法”

我们可以参考shared_ptr类那样的机制,对资源设计“引用计数法”。
此机制为:当引用计数为0时,我们希望做的是解锁资源而不是删除资源,但是我们的shared_ptr提供一个“删除器”,删除器可以是一个函数或函数对象,因此下面我们为mutexPtr提供了unlokc函数,当引用计数为0时就会调用unlock函数,将Mutex对象解锁。

class Lock
{
public:
    explicit Lock(Mutex* pm) 
        :mutexPtr(pm,unlock) //提供unlock函数为删除器
    {
        lock(mutexPtr.get()); //条款15会 谈到 get 函数
    }
private:
    std::shared_ptr<Mutex> mutexPtr; //采用智能指针代替普通指针
};

四、总结

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

普通而常见的 RAII class copying 行为是:抑制 copying、实行引用计数法。不过其他行为也都可能被实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值