Effective C++ 学记之14 在资源管理类中 小心 copying行为

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


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



auto_ptr和shared_ptr的观念表现在heap-head资源上。除此之外的其他资源而言,也可能我们需要创建自己的资源管理类。
假设我们使用C API函数处理类型为Mutex的互斥对象(mutex objects),共有lock和unlock两个函数。
void lock(Mutex* pm);//锁定pm所指的互斥器
void unlock(Mutex* pm);//接触互斥器锁定

创建一个Lock class 来管理机锁。
class Lock{
public:
    explicit Lock(Mutex* pm):mutexPtr(pm)
    {lock(mutexPtr);}

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

使用:
Mutex m;
...
{
Lock ml(&m);//锁定互斥器
...
}//在区块末尾,自动解除互斥器锁定

此时如果Lock对象被复制:
Lock ml1(&m); //锁定m
Lock ml2(ml1);
结果导致加锁1次,释放时解锁2次?

如果没有必要应该禁用复制构造函数和赋值操作符
如果没有按需要定义复制构造函数和赋值操作符,那么得到的结果通常是:非内存资源被创建一次,释放多次。
禁止方式:将copying操作声明为private。
class Lock:private Uncopyable{
public:
    ...
};

如果需要复制,重新定义复制构造函数和赋值操作符是必须的。
怎么写它们是一个问题,具体的方案依赖于实际的需要, 可以使用深拷贝,也可以使用类似于 shared_ptr 的引用计数机制,或者传递所有权。

引用计数机制

复制RAII对象时,将该资源的“被引用数”递增。例:shared_ptr

shared_ptr的缺省行为是“当引用次数为0时删除所指物”,但是上面的例子我们想要的动作是解除lock而非删除。
好在shared_ptr允许指定“删除器”:

class Lock{
public:
    explicit Lock(Mutex* pm):mutexPtr(pm, unlock) //以某个mutex初始化shared_ptr,并以unlock函数为删除器
    {lock(mutexPtr.get());} //条款15

    ~Lock(){unlock(mutexPtr);} //释放资源
private:
    std::tr1::shared_ptr<Mutex> mutexPtr;
};

深度拷贝
某些标准字符串类型是“指向heap内存”之指针构成。这样的字符串对象被复制,不论指针或其所指内存都会被制作出一个复件。
这样的字符串展现深度复制行为。

转移底部资源的拥有权

auto_ptr奉行的复制意义:RAII对象被复制,资源的拥有权从被复制物转移到目标物。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值