日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++?Boost?weak_ptr智能指針超詳細講解_C 語言

作者:無水先生 ? 更新時間: 2022-12-14 編程語言

一、提要

在 C++11 中,boost::weak_ptr是另一類智能指針,一般是用COM組件生成、調用,本文闡述這種指針的特點和用法。

二、特別智能指針(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 進行初始化。它最重要的成員函數是 lock()。 lock() 返回一個 boost::shared_ptr ,它與用于初始化弱指針的共享指針共享所有權。如果共享指針為空,則返回的指針也將為空。

boost::weak_ptr 是有意義的,只要一個函數需要與一個由共享指針管理的對象一起工作,但對象的生命周期不依賴于函數本身。該函數只能使用該對象,只要它由程序中其他位置的至少一個共享指針擁有。如果共享指針被重置,則對象無法保持活動狀態,因為相應函數內有一個額外的共享指針。

示例 1 在 main() 中創建了兩個線程。第一個線程執行函數 reset(),該函數接收對共享指針的引用。第二個線程執行函數 print(),該函數接收對弱指針的引用。這個弱指針之前已經用共享指針初始化了。

程序啟動后,reset() 和 print() 會同時執行。但是,無法預測執行順序。這會導致當對象被 print() 訪問時,reset() 會破壞該對象的潛在問題。

弱指針通過以下方式解決了這個問題:調用 lock() 返回一個共享指針,該指針指向一個有效對象(如果在調用時存在一個有效對象)。如果不是,則共享指針設置為 0,相當于一個空指針。

boost::weak_ptr 本身對對象的生命周期沒有任何影響。為了安全地訪問 print() 函數中的對象,lock() 返回一個 boost::shared_ptr。這保證了即使不同的線程嘗試釋放對象,由于返回的共享指針,它仍將繼續存在。

示例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 會跟蹤引用特定對象的共享指針的數量,但開發人員在使用 boost::intrusive_ptr 時必須這樣做。如果其他類已經跟蹤引用,這可能是有意義的。

boost::intrusive_ptr 在 boost/intrusive_ptr.hpp 中定義。

示例 2 使用 COM 提供的功能,因此只能在 Windows 上構建和運行。 COM 對象是 boost::intrusive_ptr 的一個很好的例子,因為它們跟蹤引用它們的指針的數量。內部引用計數器可以通過成員函數 AddRef() 和 Release() 遞增或遞減 1。一旦計數器達到 0,COM 對象就會自動銷毀。

??? 從 intrusive_ptr_add_ref() 和 intrusive_ptr_release() 調用兩個成員函數 AddRef() 和 Release()。 Boost.Intrusive 希望開發人員定義這兩個函數,當引用計數器必須遞增或遞減時,它們會自動調用。傳遞給這些函數的參數是指向用于實例化類模板 boost::intrusive_ptr 的類型的指針。

此示例中使用的 COM 對象稱為 FileSystemObject,默認情況下可在 Windows 上使用。它提供對底層文件系統的訪問,例如,檢查給定目錄是否存在。在示例 1.9 中,檢查了名為 C:\Windows 的目錄是否存在。其內部工作方式僅取決于 COM,與 boost::intrusive_ptr 的功能無關。關鍵是一旦侵入指針 disp 在 check_windows_folder() 結束時超出范圍,函數 intrusive_ptr_release() 就會被自動調用。這反過來會將 FileSystemObject 的內部引用計數器減為 0 并銷毀該對象。

傳遞給 boost::intrusive_ptr 的構造函數的參數 false 會阻止 intrusive_ptr_add_ref() 被調用。當使用 CoCreateInstance() 創建 COM 對象時,計數器已設置為 1。因此,不得使用 intrusive_ptr_add_ref() 遞增。

原文鏈接:https://yamagota.blog.csdn.net/article/details/127045971

欄目分類
最近更新