zoukankan      html  css  js  c++  java
  • C++11 shared_ptr(智能指针)

    在确保new动态分配的内存空间在使用结束之后,释放是一件麻烦事。C++11模板库的头文件中定义的智能指针,即shared_ptr模板,就是用来解决这个问题的。
    它是将new运算符返回的指针p交给一个shared_ptr对象“托管”,就不用担心要在哪里写delete p语句 ---实际根本不需要编写这条语句,托管p的shared_ptr对象在消亡时会自动执行delete p,而且,该shared_ptr对象能像指针p一样使用,即假设托管p的shared_ptr的shared_ptr对象叫做ptr,那么*ptr就是p指向的对象。

    通过shared_ptr的构造函数,可以让shared_ptr对象托管一个new运算符范围的指针,写法如下:

    shared_ptr<T> ptr(new T);//T可以是int、char、类等类型
    

    此后,ptr就可以像T*类型的指针一样使用,即*ptr就是用new 动态分配的那个对象
    多个shared_ptr对象可以共同托管一个指针p,当所有曾经托管p的shared_ptr对象都解除了对其的托管时,就执行delete p
    实例:

    #include <iostream>
    #include <memory>
    using namespace std;
    class A
    {
    public:
        int i;
        A(int n):i(n) { };
        ~A() { cout << i << " " << "destructed" << endl; }
    };
    int main()
    {
        shared_ptr<A> sp1(new A(2)); //A(2)由sp1托管,
        shared_ptr<A> sp2(sp1);       //A(2)同时交由sp2托管
        shared_ptr<A> sp3;
        sp3 = sp2;   //A(2)同时交由sp3托管
        cout << sp1->i << "," << sp2->i <<"," << sp3->i << endl;
        A * p = sp3.get();      // get返回托管的指针,p 指向 A(2)
        cout << p->i << endl;  //输出 2
        sp1.reset(new A(3));    // reset导致托管新的指针, 此时sp1托管A(3)
        sp2.reset(new A(4));    // sp2托管A(4)
        cout << sp1->i << endl; //输出 3
        sp3.reset(new A(5));    // sp3托管A(5),A(2)无人托管,被delete
        cout << "end" << endl;
        return 0;
    }
    

    程序的输出结果如下:
    2,2,2
    2
    3
    2 destructed
    end
    5 destructed
    4 destructed
    3 destructed

    可以用第 14 行及第 16 行的形式让多个 sharecLptr 对象托管同一个指针。这多个 shared_ptr 对象会共享一个对共同托管的指针的“托管计数”。有 n 个 shared_ptr 对象托管同一个指针 p,则 p 的托管计数就是 n。当一个指针的托管计数减为 0 时,该指针会被释放。shared_ptr 对象消亡或托管了新的指针,都会导致其原托管指针的托管计数减 1。

    第 20、21 行,shared_ptr 的 reset 成员函数可以使得对象解除对原托管指针的托管(如果有的话),并托管新的指针。原指针的托管计数会减 1。

    输出的第 4 行说明,用 new 创建的动态对象 A(2) 被释放了。程序中没有写 delete 语句,而 A(2) 被释放,是因为程序的第 23 行执行后,已经没有 shared_ptr 对象托管 A(2),于是 A(2) 的托管计数变为 0。最后一个解除对 A(2) 托管的 shared_ptr 对象会释放 A(2)。

    main 函数结束时,sp1、sp2、sp3 对象消亡,各自将其托管的指针的托管计数减为 0,并且释放其托管的指针,于是会有以下输出:
    5 destructed
    4 destructed
    3 destructed

    只有指向动态分配的对象的指针才能交给 shared_ptr 对象托管。将指向普通局部变量、全局变量的指针交给 shared_ptr 托管,编译时不会有问题,但程序运行时会出错,因为不能析构一个并没有指向动态分配的内存空间的指针


    注意
    不能使用下面的方式使两个shared_ptr对象托管同一个指针

    A* p = new A(10);
    shared_ptr <A> sp1(p), sp2(p);
    

    sp1 和 sp2 并不会共享同一个对 p 的托管计数,而是各自将对 p 的托管计数都记为 1(sp2 无法知道 p 已经被 sp1 托管过)。这样,当 sp1 消亡时要析构 p,sp2 消亡时要再次析构 p,这会导致程序崩溃。

    参考链接:http://c.biancheng.net/view/430.html
  • 相关阅读:
    IIS配置ThinkPHP重写
    Redis安装
    ubuntu学习笔记
    PHP连接MySQL数据库SELinux中一些setsebool的用法
    centos+frp
    centos7.6安装nginx
    在CentOS 7-8上安装PHP 8.0
    centos7安装.net5.0(core)
    阿里云服务器配置清单
    阿里云服务器centos7.6安装mysql8.0.23
  • 原文地址:https://www.cnblogs.com/whiteBear/p/12601945.html
Copyright © 2011-2022 走看看