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


    请牢记:

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

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

    auto_ptr和tr1::shared_ptr的观念表现在heap_based资源上。然而并非所有资源都是heap_based,对于非heap_based资源而言,需要建立自己的资源管理类。

    假设我们使用C API函数出来类型为Mutex的互斥器对象(mutex objects),共有lock和unlock两个函数。

    void lock(Mutex* pm);		//锁定pm所指的互斥器
    void unlock(Mutex* pm);		//将互斥器解除锁定
    

    为确保绝不会忘记将一个被锁住的Mutex解锁,创建一个Lock class 来管理机锁。这样的class的基本结构由RAII守则支配,也就是“资源在构造期间获得,在析构期间释放”:

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

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

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

    如果此时Lock对象被复制:

    Lock ml1(&m);    //锁定m
    Lock ml2(ml1);   //将ml1复制到ml2上,会发生什么?
    

    可能有以下两种选择:

    禁止复制:许多时候允许RAII对象复制并不合理:

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

    class Lock : private Uncopyable  //禁止复制。见条款6
    { 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对象被复制,资源的拥有权从被复制物转移到目标物。

     

  • 相关阅读:
    atcoder 2017Code festival C ——D题 Yet Another Palindrome Partitioning(思维+dp)
    51nod 1089最长回文子串V2 (manacher)
    Codeforces Round #362(Div1) D Legen...(AC自动机+矩阵快速幂)
    51nod 1532 带可选字符的多字符串匹配(位运算)
    51nod 1317 相似字符串对(容斥原理+思维)
    51nod 1526 分配笔名(字典树+贪心)
    51nod 1292 字符串中的最大值V2(后缀自动机)
    51nod 1277字符串中的最大值(拓展kmp)
    SPOJ:[DIVCNT3]Counting Divisors
    单纯形法模板
  • 原文地址:https://www.cnblogs.com/lwenwen/p/3472312.html
Copyright © 2020-2023  润新知