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

目录

1.前言

2.建立class管理锁

3.若出现复制现象,会出现什么事?


1.前言

        并非所有资源都是heap-based,对那类资源而言,像auto_ptr和share_ptr这类指针往往不适合作为资源管理者(resource handles)。所有,需要建立自己的资源管理类。

        假如使用C中的API函数处理类型为Mutex的互斥器对象(关于mutex的知识:【线程(二)】——互斥量的详细解析_线程互斥量-CSDN博客),共有lock和unlock俩函数可用:

void lock(Mutex* pm);//锁定pm所指向的互斥器

void unlock(Mutex* pm);//将互斥器解锁

为确保绝不会忘记将一个被锁住的Mutex解锁,需要建立一个class类来管理机锁。

2.建立class管理锁

        为了实现上面的目的,该类的基本结构由RAII守则支撑,既“资源在构造期间获得,在析构期间释放”:

class Lock{
    
public:
    explict Lock(Mutex* pm):mutexPtr(pm)
    {
        lock(mutexPtr);//上锁
    }

    ~Lock()
    {
        unlock(mutexPtr);//解锁
    }

    private:
        Mutex* mutexPtr;
}

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

Mutex m;//定义所需的互斥器
...
{//建立一个区块用来定义critical section
    Lock ml(&m);//锁定互斥器
    ...//执行critical section内的操作

}    //在区块末尾,自动解除互斥器的锁定

3.若出现复制现象,会出现什么事?

倘若:

Lock ml1(&m);//锁定m
Lock ml2(ml1);调用默认的拷贝构造函数,将ml1复制到ml2上,这会发生什么事?

        这个一般化问题是每个人都会用到的,即:“当RAII对象被复制,会发生什么事“,大多数会选择两种可能:

1.禁止复制

许多时候允许RAII对象被复制并不合理,对一个像Lock这样是存在这种现场的。如果复制操作对RAII Class并不合理,应该禁止复制。具体操作为将copying操作声明为private(条款6:若不想使用编译器自动生成的函数,就该明确拒绝-CSDN博客)。对Lock而言看起来是这样的:

class Lock:private Uncopyable//禁止复制,可见条款6
{
    public:
    ...

}

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

引入share_ptr,在复制RAII对象时,应该将资源的”被引用数“递增,直到它的最后一个使用者被销毁。

一般只要类里面存在trl::share_ptr成员变量,就可实现引用复制操作(reference-counting copy),share_ptr所引用的次数为0时删除其所指的对象,但当用在Mutex时候,我们想要的操作是释放锁定而非删除。幸运的是trl::share_ptr也允许指定所谓的”删除器“,那是一个函数或者函数对象,当引用次数为0时候便被调用(此机能不存在于auto_ptr-它总会将其指针删除)。注意的是删除器对trl::share_ptr构造函数而言是可有可无的第二个参数,所有代码如下:

class Lock{
    public:
    explict Lock(Mutex* pm)::mutexPtr(pm,unlock)//以Mutex初始化share_ptr
    {
        lock(mutexPtr.get());见条款15
    }
    
    private:
        std::trl::shared_ptr<Mutex> mutexPtr;//使用share_ptr替换raw pointer
}

这里Lock class为什么不再声明析构函数,见条款5(条款5:了解C++默默编写并调用哪些函数-CSDN博客)。而mutexPtr的析构函数会在引用次数为0时候调用trl::share_ptr的删除器(本例为unlock)

3.复制资源管理对象时,进行深拷贝

4.转移底部资源的拥有权,比如auto_ptr的操作

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值