std::enable_shared_from_this使用場景
在很多場合,經常會遇到一種情況,如何安全的獲取對象的this指針,一般來說我們不建議直接返回this指針,可以想象下有這么一種情況,返回的this指針保存在外部一個局部/全局變量,當對象已經被析構了。
但是外部變量并不知道指針指向的對象已經被析構了,如果此時外部使用了這個指針就會發生程序奔潰。既要像指針操作對象一樣,又能安全的析構對象,很自然就想到,智能指針就很合適!
那么智能指針如何使用呢?現在我們來看一段代碼。
#include 《iostream》 #include 《memory》 class Widget{ public: Widget(){ std::cout 《《 “Widget constructor run” 《《 std::endl; } ~Widget(){ std::cout 《《 “Widget destructor run” 《《 std::endl; } std::shared_ptr《Widget》 GetSharedObject(){ return std::shared_ptr《Widget》(this); } }; int main() { std::shared_ptr《Widget》 p(new Widget()); std::shared_ptr《Widget》 q = p-》GetSharedObject(); std::cout 《《 p.use_count() 《《 std::endl; std::cout 《《 q.use_count() 《《 std::endl; return 0; }
編譯運行后程序輸出如下:
Widget constructor run 1 1 Widget destructor run Widget destructor run 22:06:45: 程序異常結束。
從輸出我們可以看到,調用了一次構造函數,卻調用了兩次析構函數,很明顯這是不正確的。而std::enable_shared_from_this正是為了解決這個問題而存在。
02
std::enable_shared_from_this原理和實戰
前面我們說使用std::enable_shared_from_this能解決安全獲取this指針的問題。在使用之前,我們先來了解下std::enable_shared_from_this是什么?為什么能解決這個問題?std::enable_shared_from_this定義如下:
template《class _Tp》 class _LIBCPP_TEMPLATE_VIS enable_shared_from_this { mutable weak_ptr《_Tp》 __weak_this_; protected: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR enable_shared_from_this() _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY enable_shared_from_this(enable_shared_from_this const&) _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY enable_shared_from_this& operator=(enable_shared_from_this const&) _NOEXCEPT {return *this;} _LIBCPP_INLINE_VISIBILITY ~enable_shared_from_this() {} public: _LIBCPP_INLINE_VISIBILITY shared_ptr《_Tp》 shared_from_this() {return shared_ptr《_Tp》(__weak_this_);} _LIBCPP_INLINE_VISIBILITY shared_ptr《_Tp const》 shared_from_this() const {return shared_ptr《const _Tp》(__weak_this_);} #if _LIBCPP_STD_VER 》 14 _LIBCPP_INLINE_VISIBILITY weak_ptr《_Tp》 weak_from_this() _NOEXCEPT { return __weak_this_; } _LIBCPP_INLINE_VISIBILITY weak_ptr《const _Tp》 weak_from_this() const _NOEXCEPT { return __weak_this_; } #endif // _LIBCPP_STD_VER 》 14 template 《class _Up》 friend class shared_ptr; };
std::enable_shared_from_this是模板類,內部有個_Tp類型weak_ptr指針,調用shared_from_this成員函數便可獲取到_Tp類型智能指針,從這里可以看出,_Tp類型就是我們的目標類型。
再來看看std::enable_shared_from_this的構造函數都是protected,因此不能直接創建std::enable_from_shared_from_this類的實例變量,只能作為基類使用。因此使用方法如下代碼所示:
#include 《iostream》 #include 《memory》 class Widget : public std::enable_shared_from_this《Widget》{ public: Widget(){ std::cout 《《 “Widget constructor run” 《《 std::endl; } ~Widget(){ std::cout 《《 “Widget destructor run” 《《 std::endl; } std::shared_ptr《Widget》 GetSharedObject(){ return shared_from_this(); } }; int main() { std::shared_ptr《Widget》 p(new Widget()); std::shared_ptr《Widget》 q = p-》GetSharedObject(); std::cout 《《 p.use_count() 《《 std::endl; std::cout 《《 q.use_count() 《《 std::endl; return 0; }
這里為什么要創建智能指針p而不是直接創建裸指針p?根本原因在于std::enable_shared_from_this內部的weak_ptr,若只是創建裸指針p,那么p被delete后仍然面對不安全使用內部this指針問題。
因此p只能被定義為智能指針。當p被定義為shared_ptr智能指針后,p指針引用計數是1(weak_ptr不會增加引用計數),再通過shared_from_this獲取內部this指針的智能指針,則p的引用計數變為2。
現編譯運行輸出如下:
Widget constructor run 2 2 Widget destructor run
正確的返回了智能指針,p和q的引用計數都是2,且只調用了一次構造函數和析構函數,不會錯誤的析構對象多次。
編輯:jq
-
STD
+關注
關注
0文章
36瀏覽量
14398
原文標題:C++里std::enable_shared_from_this是干什么用的?
文章出處:【微信號:harmonyos_developer,微信公眾號:harmonyos_developer】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
脈沖信號分析儀?的原理和應用場景
混合信號分析儀的原理和應用場景
多用示波器的原理和應用場景
倍頻器的技術原理和應用場景
系統放大器的技術原理和應用場景
OTA測試暗箱的技術原理和應用場景
實時示波器的技術原理和應用場景
源測量單元設備的技術原理和應用場景
太陽膜測試儀的技術原理和應用場景
超聲波測厚儀的技術原理和應用場景
如何對MIL-STD-1553B進行選型
![如何對MIL-<b class='flag-5'>STD</b>-1553B進行選型](https://file1.elecfans.com/web2/M00/05/37/wKgZombX-qeAT8RwAABhY1G4Nng979.png)
評論