• 条款13:以对象管理资源


    转自:https://blog.csdn.net/coolwriter/article/details/79720921

    常用的智能指针有memory头文件里面的auto_ptr,还有boost库里的shared_ptr。两者的实现机制不同,但功能是类似的,就是能自动管理资源。他们体现的思想就是RAII(Resources Acquisition Is Initialzeation 资源取得的时机便是初始化时机)。
    举个形象的例子就是:

    auto_ptr ap(new int(10));

    或者是:

    shared_ptr sp(new int(10));

    可以看到,这里根本就没有出现原生指针,而是直接将new出来的内存交给了一个“管理者”。这个管理者可以是auto_ptr,也可以是shared_ptr,他们的存在,使得程序员可以真的忘记delete了,当ap或者sp的生命周期结束时,他们会将资源释放出来,交还给系统。比如:

    void fun()
    {
    auto_ptr<int> ap(new int(10));
    *ap = 20;
    }
    // ap 在fun()结束后会自动回收掉
    

      

    auto_ptr和shared_ptr的区别在于管理方法不同。

    auto_ptr这个管理者是一个很霸气的boss,他只想独管资源,而不允许其他管理者插手,否则他就退出管理,把这个资源交给另一方,自己再也不碰了。

    举个例子:

    auto_ptr<int> boss1(new int(10)); // 这个时候boss1对这个资源进行管理
    
    auto_ptr<int> boss2(boss1); 
    // 这个时候boss2要插手进来,boss1很生气,所以把管理权扔给了boss2,自己就不管事了。所以boss2持有这个资源,而boss1不再持有(持有的是null)。
    

    所以同一时刻,只有一个auto_ptr能管理相同的资源。
    这里还是有必要解释一下这句话的,比如:

     auto_ptr<int> boss1(new int(10)); 
     auto_ptr<int> boss2(new int(10));

    boss1还持有资源吗?答案是有的,因为new执行了两次,虽然内存空间里的初始值是一样的,但地址并不同,所以不算相同的资源。
    再来,为了把问题讲清楚,这里就让原生指针再出场一下

     int *p = new int(10);
     auto_ptr<int> boss1(p);
     auto_ptr<int> boss2(p);

    boss1还持有资源吗?
    答案是当程序运行到第三句的时候,就弹出assertion failed的红叉,程序崩溃了,为什么会这样呢?因为p所指向的是同一块资源,所以boss2发出管理手段后,boss1肯定要有动作的。第三句话调用boss2的构造函数,但构造函数中boss2识别出来p所指向的资源已经被占用了,所以会assertion failed。
    auto_ptr不支持STL容器,因为容器要求“可复制”,但auto_ptr只能有一个掌握管理权。另外,auto_ptr也不能用于数组,因为内部实现的时候,用的是delete,而不是delete[]。

    shared_ptr则顾名思义,他是一个分享与合作的管理者,他的内部实现是引用计数型的,每多一次引用,计数值就会+1,而每一次引用的生命周期结束时,计数值就会-1,当计数值为0的时候,说明内存没有管理者管理了,最后一个管理这个内存的管理者就会将之释放。

    再回到我们之前的例子:

     shared_ptr<int> boss1(new int(10)); // 这个时候boss1对这个资源进行管理
     shared_ptr<int> boss2(boss1); // boss2携手boss1对这个资源进行管理

    注意这个时候boss1并没有交出管理权,boss2的加入只对对象内部的计数指针造成了影响,在外部就像什么也没发生一样,可以使用boss1和boss2来管理资源。

    最后总结一下:

    1. 为了防止资源泄漏,使用RAII思想,它们在构造函数中获得资源,并在析构函数中释放资源。

    2. 两个常用的RAII类是shared_ptr和auto_ptr,但前者一般是更佳的选择,因为其copy行为比较直观,若选择auto_ptr,复制动作会使它指向null。









  • 相关阅读:
    CSS命名法
    CSS伪类
    CSS总结
    CSS应用给网页元素的几种方式总结
    CSS语法小记
    细谈WEB标准
    Spark 个人实战系列(1)--Spark 集群安装
    HBase 实战(1)--HBase的数据导入方式
    shell 脚本实战笔记(9)--linux自动批量添加用户
    shell 脚本实战笔记(8)--ssh免密码输入执行命令
  • 原文地址:https://www.cnblogs.com/zyj23/p/13908816.html
Copyright © 2020-2023  润新知