zoukankan      html  css  js  c++  java
  • C++11 新特性之智能指针(shared_ptr, unique_ptr, weak_ptr)

     这是C++11新特性介绍的第五部分,涉及到智能指针的相关内容(shared_ptr, unique_ptr, weak_ptr)。

    shared_ptr

    shared_ptr 基本用法

           shared_ptr采用引用计数的方式管理所指向的对象。当有一个新的shared_ptr指向同一个对象时(复制shared_ptr等),引用计数加1。当shared_ptr离开作用域时,引用计数减1。当引用计数为0时,释放所管理的内存。
           这样做的好处在于解放了程序员手动释放内存的压力。之前,为了处理程序中的异常情况,往往需要将指针手动封装到类中,通过析构函数来释放动态分配的内存;现在这一过程就可以交给shared_ptr去做了。
           一般我们使用make_shared来获得shared_ptr。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    cout<<"test shared_ptr base usage:"<<endl;
    shared_ptr<string> p1 = make_shared<string>("");
    if(p1 && p1->empty())
    *p1 = "hello";
     
    auto p2 = make_shared<string>("world");
    cout<<*p1<<' '<<*p2<<endl;
     
    cout<<"test shared_ptr use_count:"<<endl;
    cout<<"p1 cnt:"<<p1.use_count()<<" p2 cnt:"<<p2.use_count()<<endl;
     
    auto p3 = p2;
    cout<<"p1 cnt:"<<p1.use_count()<<" p2 cnt:"<<p2.use_count()<<" p3 cnt:"<<p3.use_count()<<endl;
    p2 = p1;
    cout<<"p1 cnt:"<<p1.use_count()<<" p2 cnt:"<<p2.use_count()<<" p3 cnt:"<<p3.use_count()<<endl;

    shared_ptr 和 new

           shared_ptr可以使用一个new表达式返回的指针进行初始化。

    1
    2
    3
    4
    cout<<"test shared_ptr and new:"<<endl;
    shared_ptr<int> p4(new int(1024));
    //shared_ptr<int> p5 = new int(1024); // wrong, no implicit constructor
    cout<<*p4<<endl;

           但是,不能将一个new表达式返回的指针赋值给shared_ptr。另外,特别需要注意的是,不要混用new和shared_ptr!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    void process(shared_ptr<int> ptr)
    {
    cout<<"in process use_count:"<<ptr.use_count()<<endl;
    }
     
    cout<<"don't mix shared_ptr and normal pointer:"<<endl;
    shared_ptr<int> p5(new int(1024));
    process(p5);
    int v5 = *p5;
    cout<<"v5: "<<v5<<endl;
     
    int *p6 = new int(1024);
    process(shared_ptr<int>(p6));
    int v6 = *p6;
    cout<<"v6: "<<v6<<endl;

           上面的程序片段会输出:

    1
    2
    3
    4
    5
    in process use_count:2
    v5: 1024
    in process use_count:1
    v6: 0
    cout<<"v6: "<<v6<<endl;

           可以看到,第二次process p6时,shared_ptr的引用计数为1,当离开process的作用域时,会释放对应的内存,此时p6成为了悬挂指针。所以,一旦将一个new表达式返回的指针交由shared_ptr管理之后,就不要再通过普通指针访问这块内存!

    shared_ptr.reset

           shared_ptr可以通过reset方法重置指向另一个对象,此时原对象的引用计数减一。

    1
    2
    3
    4
    cout<<"test shared_ptr reset:"<<endl;
    cout<<"p1 cnt:"<<p1.use_count()<<" p2 cnt:"<<p2.use_count()<<" p3 nt:"<<p3.use_count()<<endl;
    p1.reset(new string("cpp11"));
    cout<<"p1 cnt:"<<p1.use_count()<<" p2 cnt:"<<p2.use_count()<<" p3 cnt:"<<p3.use_count()<<endl;

    shared_ptr deleter

           可以定制一个deleter函数,用于在shared_ptr释放对象时调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void print_at_delete(int *p)
    {
    cout<<"deleting..."<<p<<' '<<*p<<endl;
    delete p;
    }
     
    cout<<"test shared_ptr deleter:"<<endl;
    int *p7 = new int(1024);
    shared_ptr<int> p8(p7, print_at_delete);
    p8 = make_shared<int>(1025);

    unique_ptr

    unique_ptr 基本用法

           unique_ptr对于所指向的对象,正如其名字所示,是独占的。所以,不可以对unique_ptr进行拷贝、赋值等操作,但是可以通过release函数在unique_ptr之间转移控制权。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cout<<"test unique_ptr base usage:"<<endl;
    unique_ptr<int> up1(new int(1024));
    cout<<"up1: "<<*up1<<endl;
    unique_ptr<int> up2(up1.release());
    cout<<"up2: "<<*up2<<endl;
    //unique_ptr<int> up3(up1); // wrong, unique_ptr can not copy
    //up2 = up1; // wrong, unique_ptr can not copy
    unique_ptr<int> up4(new int(1025));
    up4.reset(up2.release());
    cout<<"up4: "<<*up4<<endl;

    unique_ptr 作为参数和返回值

           上述对于拷贝的限制,有两个特殊情况,即unique_ptr可以作为函数的返回值和参数使用,这时虽然也有隐含的拷贝存在,但是并非不可行的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    unique_ptr<int> clone(int p)
    {
    return unique_ptr<int>(new int(p));
    }
     
    void process_unique_ptr(unique_ptr<int> up)
    {
    cout<<"process unique ptr: "<<*up<<endl;
    }
     
    cout<<"test unique_ptr parameter and return value:"<<endl;
    auto up5 = clone(1024);
    cout<<"up5: "<<*up5<<endl;
    process_unique_ptr(move(up5));
    //cout<<"up5 after process: "<<*up5<<endl; // would cause segmentfault

           这里的std::move函数,以后再单独具体细说^_^

    unique_ptr deleter

           unique_ptr同样可以设置deleter,和shared_ptr不同的是,它需要在模板参数中指定deleter的类型。好在我们有decltype这个利器,不然写起来好麻烦。

    1
    2
    3
    4
    5
    cout<<"test unique_ptr deleter:"<<endl;
    int *p9 = new int(1024);
    unique_ptr<int, decltype(print_at_delete) *> up6(p9, print_at_delete);
    unique_ptr<int> up7(new int(1025));
    up6.reset(up7.release());

    weak_ptr

           weak_ptr一般和shared_ptr配合使用。它可以指向shared_ptr所指向的对象,但是却不增加对象的引用计数。这样就有可能出现weak_ptr所指向的对象实际上已经被释放了的情况。因此,weak_ptr有一个lock函数,尝试取回一个指向对象的shared_ptr。

    1
    2
    3
    4
    5
    6
    7
    cout<<"test weak_ptr basic usage:"<<endl;
    auto p10 = make_shared<int>(1024);
    weak_ptr<int> wp1(p10);
    cout<<"p10 use_count: "<<p10.use_count()<<endl;
    //p10.reset(new int(1025)); // this will cause wp1.lock() return a false obj
    shared_ptr<int> p11 = wp1.lock();
    if(p11) cout<<"wp1: "<<*p11<<" use count: "<<p11.use_count()<<endl;

    总结

           1.shared_ptr采用引用计数的方式管理所指向的对象。
           2.shared_ptr可以使用一个new表达式返回的指针进行初始化;但是,不能将一个new表达式返回的指针赋值给shared_ptr。
           3.一旦将一个new表达式返回的指针交由shared_ptr管理之后,就不要再通过普通指针访问这块内存。
           4.shared_ptr可以通过reset方法重置指向另一个对象,此时原对象的引用计数减一。
           5.可以定制一个deleter函数,用于在shared_ptr释放对象时调用。
           6.unique_ptr对于所指向的对象,是独占的。
           7.不可以对unique_ptr进行拷贝、赋值等操作,但是可以通过release函数在unique_ptr之间转移控制权。
           8.unique_ptr可以作为函数的返回值和参数使用。
           9.unique_ptr同样可以设置deleter,需要在模板参数中指定deleter的类型。
           10.weak_ptr一般和shared_ptr配合使用。它可以指向shared_ptr所指向的对象,但是却不增加对象的引用计数。
           11.weak_ptr有一个lock函数,尝试取回一个指向对象的shared_ptr。

    https://greedysky.github.io/2016/08/20/C++11%20%E6%96%B0%E7%89%B9%E6%80%A7%E4%B9%8B%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/

  • 相关阅读:
    Jmeter之http性能测试实战 非GUI模式压测 NON-GUI模式 结果解析TPS——干货(十一)
    UI Recorder 自动化测试 回归原理(九)
    UI Recorder 自动化测试 录制原理(八)
    UI Recorder 自动化测试 整体架构(七)
    UI Recorder 自动化测试 配置项(六)
    UI Recorder 自动化测试 工具栏使用(五)
    UI Recorder 自动化测试 回归测试(四)
    UI Recorder 自动化测试 录制(三)
    UI Recorder 自动化测试工具安装问题疑难杂症解决(二)
    UI Recorder 自动化测试安装教程(一)
  • 原文地址:https://www.cnblogs.com/findumars/p/11821640.html
Copyright © 2011-2022 走看看