zoukankan      html  css  js  c++  java
  • auto_ptr, unique_ptr, shared_ptr and weak_ptr智能指针讲解

    转自:https://blog.csdn.net/jxw167/article/details/72864554

    C ++库提供以下类型的智能指针的实现:

    • auto_ptr
    • unique_ptr
    • shared_ptr
    • weak_ptr

        它们都是在内存头文件中声明。

    auto_ptr

    从C ++ 11开始,此类模板已被弃用。 unique_ptr是具有相似功能但具有改进的安全性的新工具。
    auto_ptr是一个智能指针,用于管理通过新表达式获取的对象,并在auto_ptr本身被销毁时删除该对象。
    当使用auto_ptr类描述一个对象时,它存储一个指向单个分配对象的指针,该对象可以确保当它超出范围时,它指向的对象必须被自动销毁。 它基于独占所有权模式,即同一类型的两个指针不能同时指向相同的资源。 如下面的程序所示,复制或分配指针会更改所有权,即源指针必须赋予目标指针所有权。

    [cpp] view plain copy
     
    1. #include<iostream>  
    2. #include<memory>  
    3. using namespace std;  
    4.    
    5. class A  
    6. {  
    7. public:  
    8.     void show() {  cout << "A::show()" << endl; }  
    9. };  
    10.    
    11. int main()  
    12. {  
    13.     // p1 is an auto_ptr of type A  
    14.     auto_ptr<A> p1(new A);  
    15.     p1 -> show();  
    16.    
    17.     // returns the memory address of p1  
    18.     cout << p1.get() << endl;  
    19.    
    20.     // copy constructor called, this makes p1 empty.  
    21.     auto_ptr <A> p2(p1);  
    22.     p2 -> show();  
    23.    
    24.     // p1 is empty now  
    25.     cout << p1.get() << endl;  
    26.    
    27.     // p1 gets copied in p2  
    28.     cout<< p2.get() << endl;  
    29.    
    30.     return 0;  
    31. }  

    Output:

    A::show()
    0x1b42c20
    A::show()
    0          
    0x1b42c20

    auto_ptr的拷贝构造函数和赋值运算符实际上并没有复制存储的指针,而是将它们传输出去,使第一个auto_ptr对象变为空。 这是实现严格所有权的一种方法,因此只有一个auto_ptr对象可以在任何给定时间拥有该指针,即在需要复制语义的情况下不应使用auto_ptr。

    unique_ptr

    std :: unique_ptr是在C ++ 11中开发的,用于替代std :: auto_ptr。unique_ptr是具有类似功能的新工具,但具有改进的安全性(无假拷贝分配),添加功能(删除器)和数组支持。 它是一个原始指针的容器。 它明确地防止复制其包含的指针,正如正常赋值那样会发生,即它只允许底层指针的一个所有者。
    所以,当使用unique_ptr时,在任何一个资源上最多只能有一个unique_ptr,当该unique_ptr被破坏时,该资源将被自动声明。 另外,由于任何资源只能有一个unique_ptr,所以任何创建unique_ptr副本的尝试将导致编译时错误。

    [cpp] view plain copy
     
    1. unique_ptr<A> ptr1 (new A);  
    2.   
    3. // Error: can't copy unique_ptr  
    4. unique_ptr<A> ptr2 = ptr1;  

    但是,unique_ptr可以使用新的语义,即使用std :: move()函数将包含的指针的所有权转移到另一个unique_ptr。

    [cpp] view plain copy
     
    1. // Works, resource now stored in ptr2  
    2. unique_ptr<A> ptr2 = move(ptr1);   

    所以,最好使用unique_ptr,当我们想要一个指向一个对象的指针,当该单个指针被销毁时将被回收。

    [cpp] view plain copy
     
    1. // C++ program to illustrate the use of unique_ptr  
    2. #include<iostream>  
    3. #include<memory>  
    4. using namespace std;  
    5.    
    6. class A  
    7. {  
    8. public:  
    9.     void show()  
    10.     {  
    11.         cout<<"A::show()"<<endl;  
    12.     }  
    13. };  
    14.    
    15. int main()  
    16. {  
    17.     unique_ptr<A> p1 (new A);  
    18.     p1 -> show();  
    19.    
    20.     // returns the memory address of p1  
    21.     cout << p1.get() << endl;  
    22.    
    23.     // transfers ownership to p2  
    24.     unique_ptr<A> p2 = move(p1);  
    25.     p2 -> show();  
    26.     cout << p1.get() << endl;  
    27.     cout << p2.get() << endl;  
    28.    
    29.     // transfers ownership to p3  
    30.     unique_ptr<A> p3 = move (p2);  
    31.     p3->show();  
    32.     cout << p1.get() << endl;  
    33.     cout << p2.get() << endl;  
    34.     cout << p3.get() << endl;  
    35.    
    36.     return 0;  
    37. }  

    Output:

    A::show()
    0x1c4ac20
    A::show()
    0          // NULL
    0x1c4ac20
    A::show()
    0          // NULL
    0          // NULL
    0x1c4ac20

    下面的代码返回一个资源,如果我们没有显式捕获返回值,资源将被清除。 如果我们这样做,那么我们拥有该资源的独占所有权, 这样我们可以将unique_ptr看作更安全,更好的替换auto_ptr。

    [cpp] view plain copy
     
    1. unique_ptr<A> fun()  
    2. {  
    3.     unique_ptr<A> ptr(new A);  
    4.   
    5.     /* ... 
    6.        ... */  
    7.   
    8.     return ptr;  
    9. }  

    何时使用unique_ptr?
    当您想拥有资源的唯一所有权(Exclusive)时,请使用unique_ptr, 只有一个unique_ptr可以指向一个资源, 因为单个资源可以有一个unique_ptr,所以不可能将一个unique_ptr复制到另一个。

    shared_ptr

    shared_ptr是原始指针的容器。 它是一个引用计数模型,即它与shared_ptr的所有副本合作维护其包含的指针的引用计数。 因此,每当一个新的指针指向资源时,计数器就会递增,当调用对象的析构函数时递减计数器。

    引用计数:这是一种将资源数量,指针或句柄存入资源(如对象,内存块,磁盘空间或其他资源)的技术。

    引用计数大于0,直到所有的shared_ptr副本都被删除,所包含的原始指针引用的对象将不会被销毁。因此,当我们要为一个原始指针分配给多个所有者时,我们应该使用shared_ptr。
    [cpp] view plain copy
     
    1. #include<iostream>  
    2. #include<memory>  
    3. using namespace std;  
    4.    
    5. class A  
    6. {  
    7. public:  
    8.     void show()  
    9.     {  
    10.         cout<<"A::show()"<<endl;  
    11.     }  
    12. };  
    13.    
    14. int main()  
    15. {  
    16.     shared_ptr<A> p1 (new A);  
    17.     cout << p1.get() << endl;  
    18.     p1->show();  
    19.     shared_ptr<A> p2 (p1);  
    20.     p2->show();  
    21.     cout << p1.get() << endl;  
    22.     cout << p2.get() << endl;  
    23.    
    24.     // Returns the number of shared_ptr objects  
    25.     //referring to the same managed object.  
    26.     cout << p1.use_count() << endl;  
    27.     cout << p2.use_count() << endl;  
    28.    
    29.     // Relinquishes ownership of p1 on the object  
    30.     //and pointer becomes NULL  
    31.     p1.reset();  
    32.     cout << p1.get() << endl;  
    33.     cout << p2.use_count() << endl;  
    34.     cout << p2.get() << endl;  
    35.    
    36.     return 0;  
    37. }  

    Output:

    0x1c41c20
    A::show()
    A::show()
    0x1c41c20
    0x1c41c20
    2
    2
    0          // NULL
    1
    0x1c41c20
     
    何时使用shared_ptr?

    如果要共享资源的所有权,请使用shared_ptr。 很多shared_ptr可以指向单个资源。 shared_ptr维护这个引用计数,当所有shared_ptr指向资源超出范围时,资源被破坏。
     

    weak_ptr

    将weak_ptr创建为shared_ptr的副本。 它提供对一个或多个shared_ptr实例拥有的对象的访问权限,但不参与引用计数。 weak_ptr的存在或破坏对shared_ptr或其他副本没有影响。 在某些情况下需要中断shared_ptr实例之间的循环引用。

    循环依赖(shared_ptr的问题):让我们考虑一个场景,我们有两个类A和B,它们都有指向其他类的指针。 所以,它总是像A指向B和B指向A.因此,use_count永远不会达到零,并且永远不会被删除。
    这是我们使用弱指针(weak_ptr)的原因,因为它们不是引用计数。 所以,weak_ptr被声明的类没有很强的保持,即所有权不被共享,但是他们可以访问这些对象。
     
    所以,在shared_ptr的情况下,由于循环依赖关系use_count从不达到零,这是阻止使用weak_ptr的,通过将A_ptr声明为weak_ptr来消除这个问题,因此A类不拥有它,只能访问它,我们还需要检查 对象的有效性可能超出范围。 一般来说,这是一个设计问题。

    什么时候使用weak_ptr?

    当你想要从多个地方引用你的对象 - 对于那些可以忽略和释放它们的引用(所以当你尝试取消引用时,它们只会注意到对象已经不见了)。
     
    本篇博客主要是给读者对智能指针的使用做一个总结。。。。。。。。
  • 相关阅读:
    JAVA中HashMap相关知识的总结(一)
    linux进阶之路(三):vi/vim编辑器
    linux进阶之路(二):linux文件目录
    linux进阶之路(一):linux入门
    linux:lrzsz安装
    一:阿里云服务器使用及后台环境搭建
    第二篇:线程七种状态
    Git log
    redis3.0 集群实战3
    详解Linux chgrp和chown命令的用法
  • 原文地址:https://www.cnblogs.com/geowu/p/9197116.html
Copyright © 2011-2022 走看看