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

    智能指针 shared_ptr 和 new结合使用

    用make_shared函数初始化shared_ptr是最推荐的,但有的时候还是需要用new关键字来初始化shared_ptr。

    一,先来个表格,唠唠new和shared_ptr

    操作 功能描述
    shared_ptr<T> p(q) 智能指针p管理内置指针q所指向的对象;q必须指向new分配的内存,且能够转换为T*。
    shared_ptr<T> p(u) p从unique_ptr u那里接管了原来u所指向对象的所有权,并将u置为空。
    shared_ptr<T> p(q, d) p接管了内置指针q所指的对象的所有权。q必须能转换为T*。p将使用可调用对象d来代替delete。
    p.reset() 如果p是唯一指向其对象的shared_ptr,reset会释放此对象。如果没传参数q,将p置为空。
    p.reset(q) 如果传递了内置指针q,会让p指向q所指向的对象,否则会将p置为空。
    p.reset(q, d) 如果还传递了参数d,将会调用d,而不是delete来释放q

    二,智能指针和普通指针一起使用的陷阱

    void pro(shared_ptr<int> ptr){
    
    }  
    shared_ptr<int> p(new int(42));//计数器为1                                    
    pro(p);//p作为参数会进行copy递增它的计数器,在pro内部计数器是2                
    int i = *p;//计数器为1                                                        
    cout <<  i << endl;
    
    int* bad =  new int(11);
    //pro(bad);//编译错误                                                         
    pro(shared_ptr<int>(bad));//合法,但出了pro,bad所指向的内存会被释放          
    int j = *bad;//解指针bad就会产生难以预料的结果   
    

    三,也不要使用get初始化另一个智能指针或为智能指针赋值

      shared_ptr<int> p(new int(12)); 
      int* q = p.get();
      { 
        shared_ptr<int> tmp(q); 
      }//程序块结束后,q所指向的对象被释放
      int f = *p;//解指针p就会产生难以预料的结果
      cout << f << endl;
    

    四,智能指针和异常

    void f(){
        shared_ptr<int> sp(new int(11));
        //假设抛出了异常,而且在f中未捕获
    }//函数结束后shared_ptr自动释放内存
    void f1(){
        int* ip = new int(12);
        //假设delete语句前抛出了异常,而且在f中未捕获
        delete ip;
    }//函数结束后ip所指向的内存没有被释放。
    

    五,智能指针使用的最佳建议

    • 不使用相同的内置指针初始化(或reset)多个智能指针。
    • 不使用get()初始化或reset另一个智能指针。
    • 不delete get()返回的指针。
    • 如果使用了get()返回的指针,请牢记,当最后一个对应的智能指针被销毁后,你的指针就变为无效了。
    • 如果使用智能指针管理的资源不是new分配的内存,请传递给它一个删除器。

    小例子:

    #include <iostream>
    #include <memory>
    #include <vector>
    
    using namespace std;
    
    class Test{
    public:
      Test(int d = 0) : data(d){cout << "new:" << data << endl;}
      ~Test(){cout << "del:" << data << endl;}
    private:
      int data;
    };
    void my_deleter(Test* t){
      cout << "my_deleter is work" << endl;
    }
    void pro(shared_ptr<int> ptr){
    
    }
    int main(){
      //test1 reset                                                                 
      /*                                                                            
      Test* tp = new Test(1);                                                       
      shared_ptr<Test> stp(tp);                                                     
      shared_ptr<Test> stp1(stp);                                                   
      stp.reset();                                                                  
      cout << stp << endl;                                                          
      */
    
      //test2 自定义删除器                                                          
      /*                                                                            
      Test* tp = new Test(1);                                                       
      //不会调用Test的析构函数了,只调用my_deleter函数                              
      shared_ptr<Test> stp(tp, my_deleter);                                         
      shared_ptr<Test> stp1(stp);                                                   
      cout << stp.use_count() << endl;                                              
      Test* tp1 = new Test(2);                                                      
      stp1.reset(tp1, my_deleter);                                                  
      */
    
      //test3 不要混用普通指针和智能指针                                            
      /*                                                                            
      shared_ptr<int> p(new int(42));//计数器为1                                    
      pro(p);//p作为参数会进行copy递增它的计数器,在pro内部计数器是2                
      int i = *p;//计数器为1                                                        
      cout <<  i << endl;                                                           
                                                                                    
      int* bad =  new int(11);                                                      
      //pro(bad);//编译错误                                                         
      pro(shared_ptr<int>(bad));//合法,但出了pro,bad所指向的内存会被释放          
      int j = *bad;//解指针bad就会产生难以预料的结果                                
      */
    
      //test4 get的错误使用                                                         
      /*                                                                            
      shared_ptr<int> p(new int(12));                                               
      int* q = p.get();                                                             
      {                                                                             
        shared_ptr<int> tmp(q);                                                     
      }//程序块结束后,q所指向的对象被释放                                          
      int f = *p;//解指针p就会产生难以预料的结果                                    
      cout << f << endl;                                                            
      */
    }
    

    github完整代码

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

    本人微信:xiaoshitou5854

  • 相关阅读:
    HDU1862 EXCEL排序
    结构体+字符串比较大小(HDU1234开门人和关门人 )
    两个大数字相加
    Ksusha and Array (vector)
    Ksenia and Pan Scales(思维题)
    最大公约数问题(Wolf and Rabbit )
    HDU2044一只小蜜蜂(递推)
    HDU2043密码
    基础贪心算法(HDU2037今年暑假不AC)
    c# winform 关于DataGridView的一些操作(很全,绝对够用)
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9716606.html
Copyright © 2011-2022 走看看