zoukankan      html  css  js  c++  java
  • C++智能指针

      C++有4个智能指针,auto_ptr,shared_ptr,weak_ptr,unique_ptr,其中auto_ptr只有C++98支持,C++11已经弃用。

    为什么要使用智能指针?

      当申请的空间在函数结束时未进行释放时,会造成内存泄漏;

      使用智能指针可以避免内存泄漏;智能指针是一个类,用于管理一个指针,当超出了类的作用域时,会自动调用析构函数,自动释放内存空间

    auto_ptr:

      auto_ptr采用所有权模式

    1 auto_ptr<string> p1(new string ("hello") ;
    2 auto_ptr<string> p2;  
    3 
    4 //p2剥夺了p1的所有权
    5 //当后续访问p1时将会出错
    6 p2 = p1;  

    unique_ptr:

      unique_ptr能够实现独占式拥有,保证只有一个智能指针指向该对象;能够避免内存泄漏;用于替换auto_ptr。

    1 unique_ptr<string> p1 (new string ("hello"); 
    2 unique_ptr<string> p2;
    3 
    4 //出错,p1独占拥有new的对象
    5 //避免了auto_ptr中,p1不再指向有效数据的问题
    6 p2= p1; 

      当程序将一个unique_ptr对象赋值给另一个unique_ptr对象时,如果源unique_ptr对象已经存在,则不能编译通过;如果源unique_ptr对象是一个临时右值,可以编译通过;

     1 unique_ptr<string> p1(new string ("hello"));
     2 unique_ptr<string> p2;
     3 
     4 //不可以编译通过
     5 //将一个已经存在的p1赋值给p2,会留下悬挂的p1
     6 p2 = p1;      
     7                               
     8 unique_ptr<string> p3;
     9 //可以编译通过
    10 //将一个临时右值赋值给p3,不会留下悬挂的指针
    11 p3 = unique_ptr<string>(new string ("world"));  

      将临时右值赋值给p3时,调用unique_ptr的构造函数创建一个临时对象unique_ptr<string>(new string ("world")),其所有权让给p3之后,会自动销毁,所以不会留下悬挂的指针。

    shared_ptr:

      shared_ptr能够实现共享式拥有,多个智能指针可以指向相同的对象,该资源会在最后一个引用被销毁的时候(计数等于0时)释放,使用计数机制来表示对象被几个智能指针所共享;shared_ptr对象可以通过new来构造,也可以通过传入unique_ptr和weak_ptr来构造。

      shared_ptr的成员函数:

        use_count()-返回引用计数的个数;

        unique()-返回是否独占式拥有;

        swap()-交换两个智能指针所指向的对象;

        release()-当前指针释放资源所有权,计数减1;

     1 string *s1 = new string("hello");
     2 shared_ptr<string> ps1(s1);
     3 shared_ptr<string> ps2;
     4 ps2 = ps1;
     5 
     6 //use_count(),返回引用计数的个数
     7 //输出2,共有两个智能指针ps1和ps2指向字符串"hello"
     8 cout << ps1.use_count()<<endl;
     9 cout << ps2.use_count()<<endl;    
    10 
    11 //unique(),返回ps1是否独占式拥有对象
    12 //输出0,ps1和ps2共享对象
    13 cout << ps1.unique()<<endl;   
    14 
    15 string *s3 = new string("world");
    16 shared_ptr<string> ps3(s3);
    17 //交换ps1和ps3所拥有的对象
    18 swap(ps1, ps3);    
    19 
    20 //输出1,只有一个智能指针ps1指向字符串"world"
    21 cout << ps1.use_count()<<endl;
    22 //输出2,共有两个智能指针ps2和ps3指向字符串"hello"
    23 cout << ps2.use_count() << endl;    
    24 
    25 //当前指针ps2释放资源所有权,计数减一
    26 ps2.release();
    27 //输出1,只有一个智能指针ps3指向字符串"hello"
    28 cout << ps2.use_count() << endl;    

        

    weak_ptr:

      weak_ptr是一种不控制对象生命周期的智能指针,指向一个shared_ptr管理的对象;weak_ptr是一种弱引用,不会增加对象的引用计数,只提供对该对象的访问手段;而shared_ptr是一种强引用,会增加对象的引用计数,对该对象进行内存管理;

      weak_ptr用来解决shared_ptr相互引用时的死锁问题。

     1 class B;    //声明
     2 
     3 class A
     4 {
     5 public:
     6     shared_ptr<B> pb_;
     7 };
     8 
     9 class B
    10 {
    11 public:
    12     shared_ptr<A> pa_;
    13 };
    14 
    15 void fun()
    16 {
    17     //智能指针pa指向类A的对象,智能指针pb指向类B的对象
    18     //此时,pa和pb的引用计数均为1
    19     //pa指向了类A的对象,pb指向了类B的对象
    20     shared_ptr<A> pa(new A());
    21     shared_ptr<B> pb(new B());
    22 
    23     //初始化类内的shared_ptr成员
    24     //pa_也指向了类A的对象,pb_也指向了类B的对象
    25     pb->pa_ = pa;
    26     pa->pb_ = pb;
    27 
    28     //此时,pa和pb的引用计数均为2
    29     cout << pa.use_count() << endl;    
    30     cout << pb.use_count() << endl;    
    31 }
    32 
    33 int main()
    34 {   
    35     fun();
    36     return 0;
    37 }

      pa和pb之间相互引用,两个资源的引用计数均为2;当跳出fun函数时,智能指针pa和pb析构,两个资源的引用计数均变为1,两个资源没有被释放(类A和类B的析构函数没有被调用),造成死锁。

      当把类A中的shared_ptr改为weak_ptr后,资源A的引用计数为2,资源B的引用计数为1;当跳出fun函数时,智能指针pa和pb析构,资源A的引用计数变为1,资源B的引用计数变为0,资源B释放;资源B释放以后,是的资源A的引用计数变为0,资源A得到释放。

    void fun()
    {
         //智能指针pa指向类A的对象,智能指针pb指向类B的对象
         //此时,pa和pb的引用计数均为1
         //pa指向了类A的对象,pb指向了类B的对象
         shared_ptr<A> pa(new A());
         shared_ptr<B> pb(new B());
     
         //初始化类内的shared_ptr成员
         //pa_也指向了类A的对象,pb_也指向了类B的对象
         pb->pa_ = pa;
         pa->pb_ = pb;
     
         //此时,pa的引用计数均为2,pb的引用计数为1
         cout << pa.use_count() << endl;    
         cout << pb.use_count() << endl;    
    }

      shared_ptr和weak_ptr之间可以相互转换,shared_ptr可以直接赋值给weak_ptr,weak_ptr通过调用lock函数转换为shared_ptr从而赋值给shared_ptr;此外,不能通过weak_ptr直接访问对象的方法,应该先把其转换为shared_ptr以后再进行访问。

    相关链接

    C++类型转换 https://www.cnblogs.com/yongjin-hou/p/14391180.html

  • 相关阅读:
    powershell初探(七)
    powershell初探(九)
    打造一个有感觉的Vim(一)
    屏幕录像软件Wink
    注释也精彩
    解决XP专业版局域网访问故障十八招
    可以抓文字的抓图软件
    轻松玩转XP系统(一)
    Excel实战技巧之[活用条件格式]
    局域网传输工具飞鸽传书IPMessager
  • 原文地址:https://www.cnblogs.com/yongjin-hou/p/14394429.html
Copyright © 2011-2022 走看看