為什么使用enable_shared_from_this——shared_ptr兩類錯誤


在使用C++實現弱回調時,訂閱者應當維護一系列發布者的weak_ptr,而發布者注冊回調時要傳出this的shared_ptr指針,流行的實現方法是使用std::enable_shared_from_this。

初次學習這個模板類時疑問了一下為什么不能依賴this直接產生一個shared_ptr?實驗發現shared_ptr的固有特性使這樣做不是很方便。

借用MSDN的example:

 1 // std_memory_shared_from_this.cpp   
 2 // compile with: /EHsc   
 3 #include <memory>  
 4 #include <iostream>  
 5   
 6 using namespace std;  
 7   
 8 struct base : public std::enable_shared_from_this<base>  
 9 {  
10     int val;  
11   
12     shared_ptr<base> share_more()  
13     {  
14         return shared_from_this();  
15         //return make_shared<base>(*this);     //err1 
16         //return shared_ptr<base>(this);        //err2
17     }  
18 };  
19   
20 int main()  
21 {  
22     auto sp1 = make_shared<base>();  
23     auto sp2 = sp1->share_more();  
24   
25     sp1->val = 3;  
26     cout << "sp2->val == " << sp2->val << endl;  
27   
28     return 0;  
29 }   

嘗試了兩種寫法都出現了錯誤的行為,分別解釋。

err1中,輸出結果為0,make_shared實際可以看作為了完全封裝new而給shared_ptr的一個factory,作用是產生新對象,那么參數*this作為復制構造的參數,實際已經和this沒有關系了。

err2中,輸出為3,但程序結束時觸發了斷點,這也是使用智能指針應當注意的——復制行為不要依賴裸指針

通過代碼

cout << "sp2's ref count == " << sp2.use_count() << endl;

可以發現,sp2引用計數為1,因為產生它時參數為裸指針this,,它是一個新的智能指針,這就產生了問題,sp1,sp2兩個智能指針同時指向一個堆對象——析構行為時會delete兩次!

 

所以依賴shared_ptr我們很難從對象內部傳出指向自己的指針指針,use std::enable_shared_from_this。


免責聲明!

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



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