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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM