網(wǎng)站首頁 編程語言 正文
一、提要
在 C++11 中,boost::weak_ptr是另一類智能指針,一般是用COM組件生成、調(diào)用,本文闡述這種指針的特點和用法。
二、特別智能指針(Special Smart Pointers)
到目前為止介紹的每個智能指針都可以在不同的場景中單獨使用。但是,boost::weak_ptr 僅在與 boost::shared_ptr 結合使用時才有意義。 boost::weak_ptr 在 boost/weak_ptr.hpp 中定義。
示例1.Usingboost::weak_ptr
#include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <thread> #include <functional> #include <iostream> void reset(boost::shared_ptr<int> &sh) { sh.reset(); } void print(boost::weak_ptr<int> &w) { boost::shared_ptr<int> sh = w.lock(); if (sh) std::cout << *sh << '\n'; } int main() { boost::shared_ptr<int> sh{new int{99}}; boost::weak_ptr<int> w{sh}; std::thread t1{reset, std::ref(sh)}; std::thread t2{print, std::ref(w)}; t1.join(); t2.join(); }
boost::weak_ptr 必須使用 boost::shared_ptr 進行初始化。它最重要的成員函數(shù)是 lock()。 lock() 返回一個 boost::shared_ptr ,它與用于初始化弱指針的共享指針共享所有權。如果共享指針為空,則返回的指針也將為空。
boost::weak_ptr 是有意義的,只要一個函數(shù)需要與一個由共享指針管理的對象一起工作,但對象的生命周期不依賴于函數(shù)本身。該函數(shù)只能使用該對象,只要它由程序中其他位置的至少一個共享指針擁有。如果共享指針被重置,則對象無法保持活動狀態(tài),因為相應函數(shù)內(nèi)有一個額外的共享指針。
示例 1 在 main() 中創(chuàng)建了兩個線程。第一個線程執(zhí)行函數(shù) reset(),該函數(shù)接收對共享指針的引用。第二個線程執(zhí)行函數(shù) print(),該函數(shù)接收對弱指針的引用。這個弱指針之前已經(jīng)用共享指針初始化了。
程序啟動后,reset() 和 print() 會同時執(zhí)行。但是,無法預測執(zhí)行順序。這會導致當對象被 print() 訪問時,reset() 會破壞該對象的潛在問題。
弱指針通過以下方式解決了這個問題:調(diào)用 lock() 返回一個共享指針,該指針指向一個有效對象(如果在調(diào)用時存在一個有效對象)。如果不是,則共享指針設置為 0,相當于一個空指針。
boost::weak_ptr 本身對對象的生命周期沒有任何影響。為了安全地訪問 print() 函數(shù)中的對象,lock() 返回一個 boost::shared_ptr。這保證了即使不同的線程嘗試釋放對象,由于返回的共享指針,它仍將繼續(xù)存在。
示例2 .使用boost::intrusive_ptr
#include <boost/intrusive_ptr.hpp> #include <atlbase.h> #include <iostream> void intrusive_ptr_add_ref(IDispatch *p) { p->AddRef(); } void intrusive_ptr_release(IDispatch *p) { p->Release(); } void check_windows_folder() { CLSID clsid; CLSIDFromProgID(CComBSTR{"Scripting.FileSystemObject"}, &clsid); void *p; CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, __uuidof(IDispatch), &p); boost::intrusive_ptr<IDispatch> disp{static_cast<IDispatch*>(p), false}; CComDispatchDriver dd{disp.get()}; CComVariant arg{"C:\\Windows"}; CComVariant ret{false}; dd.Invoke1(CComBSTR{"FolderExists"}, &arg, &ret); std::cout << std::boolalpha << (ret.boolVal != 0) << '\n'; } int main() { CoInitialize(0); check_windows_folder(); CoUninitialize(); }
通常,boost::intrusive_ptr 的工作方式與 boost::shared_ptr 相同。但是,雖然 boost::shared_ptr 會跟蹤引用特定對象的共享指針的數(shù)量,但開發(fā)人員在使用 boost::intrusive_ptr 時必須這樣做。如果其他類已經(jīng)跟蹤引用,這可能是有意義的。
boost::intrusive_ptr 在 boost/intrusive_ptr.hpp 中定義。
示例 2 使用 COM 提供的功能,因此只能在 Windows 上構建和運行。 COM 對象是 boost::intrusive_ptr 的一個很好的例子,因為它們跟蹤引用它們的指針的數(shù)量。內(nèi)部引用計數(shù)器可以通過成員函數(shù) AddRef() 和 Release() 遞增或遞減 1。一旦計數(shù)器達到 0,COM 對象就會自動銷毀。
??? 從 intrusive_ptr_add_ref() 和 intrusive_ptr_release() 調(diào)用兩個成員函數(shù) AddRef() 和 Release()。 Boost.Intrusive 希望開發(fā)人員定義這兩個函數(shù),當引用計數(shù)器必須遞增或遞減時,它們會自動調(diào)用。傳遞給這些函數(shù)的參數(shù)是指向用于實例化類模板 boost::intrusive_ptr 的類型的指針。
此示例中使用的 COM 對象稱為 FileSystemObject,默認情況下可在 Windows 上使用。它提供對底層文件系統(tǒng)的訪問,例如,檢查給定目錄是否存在。在示例 1.9 中,檢查了名為 C:\Windows 的目錄是否存在。其內(nèi)部工作方式僅取決于 COM,與 boost::intrusive_ptr 的功能無關。關鍵是一旦侵入指針 disp 在 check_windows_folder() 結束時超出范圍,函數(shù) intrusive_ptr_release() 就會被自動調(diào)用。這反過來會將 FileSystemObject 的內(nèi)部引用計數(shù)器減為 0 并銷毀該對象。
傳遞給 boost::intrusive_ptr 的構造函數(shù)的參數(shù) false 會阻止 intrusive_ptr_add_ref() 被調(diào)用。當使用 CoCreateInstance() 創(chuàng)建 COM 對象時,計數(shù)器已設置為 1。因此,不得使用 intrusive_ptr_add_ref() 遞增。
原文鏈接:https://yamagota.blog.csdn.net/article/details/127045971
相關推薦
- 2023-12-11 Mybatis對于多對一和一對多的處理
- 2022-04-20 Python設計模式中的行為型策略模式_python
- 2023-02-05 Redis處理高并發(fā)之布隆過濾器詳解_Redis
- 2023-01-10 CentOS7?minimal?最小化安裝網(wǎng)絡設置過程_Linux
- 2022-11-10 Netcore?Webapi返回數(shù)據(jù)的三種方式示例_C#教程
- 2022-05-31 如何利用python給微信公眾號發(fā)消息實例代碼_python
- 2022-05-13 在 Dart 中更好地使用類和 Mixin
- 2022-08-19 android九宮格鎖屏控件使用詳解_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支