zoukankan      html  css  js  c++  java
  • c/c++ 智能指针 shared_ptr 使用

    智能指针 shared_ptr 使用

    上一篇智能指针是啥玩意,介绍了什么是智能指针。

    这一篇简单说说如何使用智能指针。

    一,智能指针分3类:今天只唠唠shared_ptr

    • shared_ptr
    • unique_ptr
    • weak_ptr

    二,下表是shared_ptr和unique_ptr都支持的操作

    操作 功能描述
    shared_ptr<T> sp 空智能指针,可以指向类型为T的对象
    unique_ptr<T> up 空智能指针,可以指向类型为T的对象
    p 将p用作一个条件判断,如果p指向一个对象,则为true
    *p 解引用p,获得它指向的对象
    p->mem 等价于(*p).mem,访问p所指对象的mem成员
    p.get() 返回p中保存的指针。如果指向的对象已经被释放,就是一个危险的指针
    swap(p, q)或者p.swap(q) 交换p和q中的指针

    上面操作的验证代码

    #include <memory>
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class Test{
    public:
      Test(int d = 0):data(d){cout << "cr:" << data << endl;}
      ~Test(){cout << "fr:" << data << endl;}
      void fun(){
        cout << "Test func(" << data << ")" << endl;
      }
    private:
      int data;
    };
    int main(){
      //shared_ptr<Test> sp = make_shared<Test>();                                  
      Test* pt = new Test();
      shared_ptr<Test> sp(pt);
      if(sp){
        cout << "sp指向了对象" << endl;
      }
      (*sp).fun();
      shared_ptr<int> isp;
      if(!isp){
        cout << "isp没有指向对象" << endl;
      }
      Test* tmp1 = sp.get();
      auto sp1 = make_shared<Test>(10);
      Test* tmp2 = sp1.get();
      swap(sp, sp1);
      tmp1->fun();//0
      tmp2->fun();//10
      //sp和sp1所指向的对象被交换了
      sp.get()->fun();//10
      sp1.get()->fun();//0
    
    }
    

    三,下表是shared_ptr独有的操作

    操作 功能描述
    make_shared<T>(args) 返回shared_ptr,指向一个动态分配的类型为T的对象。使用args初始化此对象。
    shared_ptr p(q) p是q的拷贝;递增q中的计数器。q中的指针必须能转化成T*。
    p = q p和q都是shared_ptr,所保存的指针必须能相互转换。递减p的引用计数;递增q的引用计数;如果p的引用计数变为0,则释放p管理的对象的内存。
    p.unique() 如果p.use_count()为1,则返回true;否则返回false
    p.use_count() 返回与p共享对象的智能指针的数量;性能很低,用于调试。

    上面操作的验证代码

      shared_ptr<Test> tsp = make_shared<Test>(11);
      cout << tsp.use_count() << endl;//1                                           
      //tsp1和tsp指向相同的对象,这个对象的计数器加1                                
      shared_ptr<Test> tsp1(tsp);
      cout << tsp.use_count() << endl;//2                                           
      //用tsp1改变了对象的data的值,所以用tsp再访问这个对象,发现对象被改变了        
      tsp1->setData(111);
      tsp->fun();//111                                                              
    
      shared_ptr<Test> q(new Test(20));
      cout << q.use_count() << endl;//1                                             
      cout << tsp.use_count() << endl;//2                                           
      //如果q不是智能指针,q指向的Test(20)这块内存就泄露了                           
      //q是智能指针,所以自动释放了Test(20)这块内存                                 
      q = tsp;
      cout << q.use_count() << endl;//3                                             
      cout << tsp.use_count() << endl;//3                                           
      if(!q.unique()){
        cout << "不是只有一个智能指针指向了某个对象" << endl;
      }
    

    四,智能指针作为函数的返回值

    shared_ptr<Test> hun(int d){
      return make_shared<Test>(d);
    }
    void use_hun1(int d){
      shared_ptr<Test> p = hun(d);
      p->fun();
    }//p离开作用域后,它指向的内存会被自动释放                                      
    shared_ptr<Test> use_hun2(int d){
      shared_ptr<Test> p = hun(d);//计数器为1                                       
      return p;//返回p时,计数器递增,为2                                           
    }//离开作用域后,计数器递减,为1,因为不为0,所以不会释放
    

    一到四的小例子:

    include <memory>
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class Test{
    public:
      Test(int d = 0):data(d){cout << "cr:" << data << endl;}
      ~Test(){cout << "fr:" << data << endl;}
      void fun(){
        cout << "Test func(" << data << ")" << endl;
      }
      void setData(int d){
        data = d;
      }
    private:
      int data;
    };
    
    //test3 智能指针作为函数的返回值                                                
    shared_ptr<Test> hun(int d){
      return make_shared<Test>(d);
    }
    void use_hun1(int d){
      shared_ptr<Test> p = hun(d);
      p->fun();
    }//p离开作用域后,它指向的内存会被自动释放                                      
    shared_ptr<Test> use_hun2(int d){
      shared_ptr<Test> p = hun(d);//计数器为1                                       
      return p;//返回p时,计数器递增,为2                                           
    }//离开作用域后,计数器递减,为1,因为不为0,所以不会释放                       
    int main(){
      //test1 shared_ptr和unique_ptr都支持的操作                                    
      /*                                                                            
      //shared_ptr<Test> sp = make_shared<Test>();                                  
      Test* pt = new Test();                                                        
      shared_ptr<Test> sp(pt);                                                      
      if(sp){                                                                       
        cout << "sp指向了对象" << endl;                                             
      }                                                                             
      (*sp).fun();                                                                  
      shared_ptr<int> isp;                                                          
      if(!isp){                                                                     
        cout << "isp没有指向对象" << endl;                                          
      }                                                                             
      Test* tmp1 = sp.get();                                                        
      auto sp1 = make_shared<Test>(10);                                             
      Test* tmp2 = sp1.get();                                                       
      swap(sp, sp1);                                                                
      tmp1->fun();                                                                  
      tmp2->fun();                                                                  
      sp.get()->fun();                                                              
      sp1.get()->fun();                                                             
      */
    
      //test2 shared_ptr独有的操作                                                   
      /*                                                                            
      shared_ptr<Test> tsp = make_shared<Test>(11);                                 
      cout << tsp.use_count() << endl;//1                                           
      //tsp1和tsp指向相同的对象,这个对象的计数器加1                                
      shared_ptr<Test> tsp1(tsp);                                                   
      cout << tsp.use_count() << endl;//2                                           
      //用tsp1改变了对象的data的值,所以用tsp再访问这个对象,发现对象被改变了        
      tsp1->setData(111);                                                           
      tsp->fun();//111                                                              
                                                                                    
      shared_ptr<Test> q(new Test(20));                                             
      cout << q.use_count() << endl;//1                                             
      cout << tsp.use_count() << endl;//2                                           
      //如果q不是智能指针,q指向的Test(20)这块内存就泄露了                           
      //q是智能指针,所以自动释放了Test(20)这块内存                                 
      q = tsp;                                                                      
      cout << q.use_count() << endl;//3                                             
      cout << tsp.use_count() << endl;//3                                           
      if(!q.unique()){                                                              
        cout << "不是只有一个智能指针指向了某个对象" << endl;                       
      }                                                                             
      */
    
      //test3 智能指针作为函数的返回值                                              
      /*                                                                            
      auto ap = use_hun2(22);                                                       
      ap->fun();                                                                    
      use_hun1(33);                                                                 
      */
    
    }
    

    github完整代码

    五,智能指针的注意事项

    把shared_ptr放入容器中时,之后不再需要全部元素,只使用其中一部分的话,要用erase删除那些不再需要使用的shared_ptr。如果不erase那些不再需要使用的shared_ptr,shared_ptr就不会释放它指向的内存。

    六,智能指针的小例子,让多个对象共享相同的状态。

    • 有个类shared_vector,里面有个shared_ptr,指向了一个vector,类shared_vector的对象a2拷贝a1时,实现a1和a2共享vector。
    • 类un_shared_vector没有使用shared_ptr,所以没有共享vector。
    include <iostream>
    #include <memory>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    class shared_vector{
    public:
      typedef vector<string>::size_type size_type;
      shared_vector():data(make_shared<vector<string>>()){}
      shared_vector(initializer_list<string> il):
        data(make_shared<vector<string>>(il)){}
      size_type size()const{return data->size();}
      bool empty()const{return data->empty();}
      //尾部插入,删除元素                                                          
      void push_back(const string& s){data->push_back(s);}
      void pop_back(){data->pop_back();}
      //访问元素                                                                    
      string& front(){return data->front();}
      string& back(){return data->back();}
    
    private:
      shared_ptr<vector<string>> data;
    };
    
    class un_shared_vector{
    public:
      typedef vector<string>::size_type size_type;
      un_shared_vector():data(vector<string>()){}
      un_shared_vector(initializer_list<string> il):data(il){}
      size_type size()const{return data.size();}
      bool empty()const{return data.empty();}
      //尾部插入,删除元素                                                          
      void push_back(const string& s){data.push_back(s);}
      void pop_back(){data.pop_back();}
      //访问元素                                                                    
      string& front(){return data.front();}
      string& back(){return data.back();}
    
    private:
      vector<string> data;
    };
    
    int main(){
      shared_vector sv{"aa","bb"};
      shared_vector sv1(sv);
      //因为sv和sv1共享同一个vector,                                               
      //所以通过sv改变vector后,通过sv1也发现了相同的改变
      sv.push_back("cc");
      cout << sv1.back() << endl;
    
      un_shared_vector usv{"11","22"};
      un_shared_vector usv1(usv);
      //因为usv和usv1不共享同一个vector,                                           
      //所以通过usv改变vector后,usv1里面的vector没有跟着变化
      usv.push_back("33");
      cout << usv1.back() << endl;
      cout << usv.back() << endl;
    }
    

    github完整代码

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    springcloud-EurekaServer模块
    springcloud-消费者订单模块
    springboot配置热部署
    swagger依赖和配置类
    springcloud-支付模块构建
    jQuery基础
    JavaScript之实例
    JavaScript之DOM
    JavaScript之BOM
    JavaScript函数与对象
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9711169.html
Copyright © 2011-2022 走看看