#Boost# Boost 智能指針
共
8345字,需瀏覽
17分鐘
·
2022-11-17 16:47
“ 文章所涉及內(nèi)容更多來自網(wǎng)絡(luò),在此聲明,并感謝知識(shí)的貢獻(xiàn)者!”
http://zh.highscore.de/cpp/boost/introduction.htmlBoost.Any 提供了一個(gè)名為boost::any 的數(shù)據(jù)類型,可以存放任意的類型。 例如,一個(gè)類型為 boost::any 的變量可以先存放一個(gè) int 類型的值,然后替換為一個(gè) std::string 類型的字符串。Boost.Array 可以把 C++數(shù)組視同 C++ 標(biāo)準(zhǔn)的容器。Boost.Asio 可用于開發(fā)異步處理數(shù)據(jù)的應(yīng)用,如網(wǎng)絡(luò)應(yīng)用。Boost.Bimap 提供了一個(gè)名為boost::bimap 的類,它類似于 std::map. 主要的差別在于 boost::bimap 可以同時(shí)從鍵和值進(jìn)行搜索。Boost.Bind 是一種適配器,可以將函數(shù)作為模板參數(shù),即使該函數(shù)的簽名與模板參數(shù)不兼容。Boost.Conversion 提供了三個(gè)轉(zhuǎn)型操作符,分別執(zhí)行向下轉(zhuǎn)型、交叉轉(zhuǎn)型,以及不同數(shù)字類型間的值轉(zhuǎn)換。Boost.DateTime 可用于以靈活的格式處理、讀入和寫出日期及時(shí)間值。Boost.Exception 可以在拋出的異常中加入額外的數(shù)據(jù),以便在 catch 處理中提供更多的信息。 這有助于更容易地調(diào)試,以及對(duì)異常情況更好地作出反應(yīng)。Boost.Filesystem 提供了一個(gè)類來處理路徑信息,還包含了幾個(gè)訪問文件和目錄的函數(shù)。Boost.Format 以一個(gè)類型安全且可擴(kuò)展的 boost::format 類替代了 std::printf() 函數(shù)。Boost.Function 簡(jiǎn)化了函數(shù)指針的定義。Boost.Interprocess 允許多個(gè)應(yīng)用通過共享內(nèi)存以快速、高效的方式進(jìn)行通信。Boost.Lambda 可以定義匿名的函數(shù)。 代碼被內(nèi)聯(lián)地聲明和執(zhí)行,避免了單獨(dú)的函數(shù)調(diào)用。Boost.Multiindex 定義了一些新的容器,它們可以同時(shí)支持多個(gè)接口,如 std::vector 和 std::map 的接口。Boost.NumericConversion提供了一個(gè)轉(zhuǎn)型操作符,可以安全地在不同的數(shù)字類型間進(jìn)行值轉(zhuǎn)換,不會(huì)生成上溢出或下溢出的條件。Boost.PointerContainer 提供了專門為動(dòng)態(tài)分配對(duì)象進(jìn)行優(yōu)化的容器。Boost.Ref 的適配器可以將不可復(fù)制對(duì)象的引用傳給需要復(fù)制的函數(shù)。Boost.Regex 提供了通過正則表達(dá)式進(jìn)行文本搜索的函數(shù)。通過 Boost.Serialization,對(duì)象可以被序列化,如保存在文件中,并在以后重新導(dǎo)入。Boost.Signal 是一個(gè)事件處理的框架,基于所謂的 signal/slot 概念。 函數(shù)與信號(hào)相關(guān)聯(lián)并在信號(hào)被觸發(fā)時(shí)自動(dòng)被調(diào)用。Boost.SmartPoiners 提供了多個(gè)智能指針,簡(jiǎn)化了動(dòng)態(tài)分配對(duì)象的管理。Boost.Spirit 可以用類似于EBNF (擴(kuò)展巴科斯范式)的語法生成詞法分析器。Boost.StringAlgorithms 提供了多個(gè)獨(dú)立的函數(shù),以方便處理字符串。Boost.System 提供了一個(gè)處理系統(tǒng)相關(guān)或應(yīng)用相關(guān)錯(cuò)誤代碼的框架。Boost.Thread 可用于開發(fā)多線程應(yīng)用。Boost.Tokenizer 可以對(duì)一個(gè)字符串的各個(gè)組件進(jìn)行迭代。Boost.Tuple 提供了泛化版的std::pair,可以將任意數(shù)量的數(shù)據(jù)組在一起。Boost.Unordered 擴(kuò)展了C++ 標(biāo)準(zhǔn)的容器,增加了boost::unordered_set 和 boost::unordered_map.Boost.Variant 可以定義多個(gè)數(shù)據(jù)類型,類似于 union, 將多個(gè)數(shù)據(jù)類型組在一起。 Boost.Variant 比 union 優(yōu)勝的地方在于它可以使用類。C++ 標(biāo)準(zhǔn) 智能指針 auto_ptr
C++標(biāo)準(zhǔn)只提供了一種智能指針: std::auto_ptr。 它基本上就像是個(gè)普通的指針: 通過地址來訪問一個(gè)動(dòng)態(tài)分配的對(duì)象。 std::auto_ptr之所以被看作是智能指針,是因?yàn)樗鼤?huì)在析構(gòu)的時(shí)候調(diào)用 delete 操作符來自動(dòng)釋放所包含的對(duì)象。
當(dāng)然這要求在初始化的時(shí)候,傳給它一個(gè)由 new 操作符返回的對(duì)象的地址。 既然 std::auto_ptr 的析構(gòu)函數(shù)會(huì)調(diào)用 delete 操作符,它所包含的對(duì)象的內(nèi)存會(huì)確保釋放掉。
RAII機(jī)制 :資源申請(qǐng)即初始化。智能指針確保在任何情況下,動(dòng)態(tài)分配的內(nèi)存都能得到正確釋放。用一個(gè)動(dòng)態(tài)分配的對(duì)象的地址來初始化智能指針,在析構(gòu)的時(shí)候釋放內(nèi)存,就確保了這一點(diǎn)。
因?yàn)槲鰳?gòu)函數(shù)總是會(huì)被執(zhí)行的,這樣所包含的內(nèi)存也將總是會(huì)被釋放。windows_handle h(OpenProcess(PROCESS_SET_INFORMATION, FALSE,
GetCurrentProcessId())); SetPriorityClass(h.handle(), HIGH_PRIORITY_CLASS); 通過 OpenProcess() 打開的資源不需要顯示的調(diào)用 CloseHandle() 來關(guān)閉。 當(dāng)然,應(yīng)用程序終止時(shí)資源也會(huì)隨之關(guān)閉。 然而,在更加復(fù)雜的應(yīng)用程序里, windows_handle 類確保當(dāng)一個(gè)資源不再使用時(shí)就能正確的關(guān)閉。 某個(gè)資源一旦離開了它的作用域——上例中 h 的作用域在 main()函數(shù)的末尾——它的析構(gòu)函數(shù)會(huì)被自動(dòng)的調(diào)用,相應(yīng)的資源也就釋放掉了。一個(gè)作用域指針獨(dú)占一個(gè)動(dòng)態(tài)分配的對(duì)象,對(duì)應(yīng)的類名為 boost::scoped_ptr。一個(gè)作用域指針不能傳遞它所包含的對(duì)象的所有權(quán)到另一個(gè)作用域指針。
一旦用一個(gè)地址來初始化,這個(gè)動(dòng)態(tài)分配的對(duì)象將在析構(gòu)階段釋放。因?yàn)橐粋€(gè)作用域指針只是簡(jiǎn)單保存和獨(dú)占一個(gè)內(nèi)存地址,所以 boost::scoped_ptr的實(shí)現(xiàn)就要比 std::auto_ptr 簡(jiǎn)單。 在不需要所有權(quán)傳遞的時(shí)候應(yīng)該優(yōu)先使用 boost::scoped_ptr 。 在這些情況下,比起 std::auto_ptr 它是一個(gè)更好的選擇,因?yàn)榭梢员苊獠唤?jīng)意間的所有權(quán)傳遞。#include <boost/scoped_ptr.hpp> boost::scoped_ptr<int> i(new int); 一經(jīng)初始化,智能指針 boost::scoped_ptr 所包含的對(duì)象,可以通過類似于普通指針的接口來訪問。get() 和 reset() 方法:前者返回所含對(duì)象的地址,后者用一個(gè)新的對(duì)象來重新初始化智能指針。
在這種情況下,新創(chuàng)建的對(duì)象賦值之前會(huì)先自動(dòng)釋放所包含的對(duì)象。boost::scoped_ptr 的析構(gòu)函數(shù)中使用delete 操作符來釋放所包含的對(duì)象。 這對(duì) boost::scoped_ptr所包含的類型加上了一條重要的限制。作用域數(shù)組的使用方式與作用域指針相似。 關(guān)鍵不同在于,作用域數(shù)組的析構(gòu)函數(shù)使用 delete[]操作符來釋放所包含的對(duì)象。 因?yàn)樵摬僮鞣荒苡糜跀?shù)組對(duì)象,所以作用域數(shù)組必須通過動(dòng)態(tài)分配的數(shù)組來初始化。對(duì)應(yīng)的作用域數(shù)組類名為 boost::scoped_array#include <boost/scoped_array.hpp> boost::scoped_array<int> i(new int[2]); 可以通過 operator[]() 操作符訪問數(shù)組中特定的元素,boost:scoped_array 也提供了 get() 和 reset() 方法,用來返回和重新初始化所含對(duì)象的地址。智能指針 boost::shared_ptr 基本上類似于 boost::scoped_ptr。 關(guān)鍵不同之處在于 boost::shared_ptr不一定要獨(dú)占一個(gè)對(duì)象。 它可以和其他 boost::shared_ptr 類型的智能指針共享所有權(quán)。
在這種情況下,當(dāng)引用對(duì)象的最后一個(gè)智能指針銷毀后,對(duì)象才會(huì)被釋放。因?yàn)樗袡?quán)可以在 boost::shared_ptr 之間共享,任何一個(gè)共享指針都可以被復(fù)制,這跟boost::scoped_ptr 是不同的。 這樣就可以在標(biāo)準(zhǔn)容器里存儲(chǔ)智能指針了——你不能在標(biāo)準(zhǔn)容器中存儲(chǔ) std::auto_ptr,因?yàn)樗鼈冊(cè)诳截惖臅r(shí)候傳遞了所有權(quán)。#include <boost/shared_ptr.hpp> std::vector<boost::shared_ptr<int> > v; v.push_back(boost::shared_ptr<int>(new int(1))); v.push_back(boost::shared_ptr<int>(new int(2))); boost::shared_ptr 能夠共享它所含對(duì)象的所有權(quán),所以保存在容器中的拷貝(包括容器在需要時(shí)額外創(chuàng)建的拷貝)都是和原件相同的。共享數(shù)組的行為類似于共享指針。 關(guān)鍵不同在于共享數(shù)組在析構(gòu)時(shí),默認(rèn)使用 delete[]操作符來釋放所含的對(duì)象。 因?yàn)檫@個(gè)操作符只能用于數(shù)組對(duì)象,共享數(shù)組必須通過動(dòng)態(tài)分配的數(shù)組的地址來初始化。共享數(shù)組對(duì)應(yīng)的類型是 boost::shared_array#include <boost/shared_array.hpp> boost::shared_array<int> i1(new int[2]); boost::shared_array<int> i2(i1); std::cout << i2[0] << std::endl; 就像共享指針那樣,所含對(duì)象的所有權(quán)可以跟其他共享數(shù)組來共享。 這個(gè)例子中定義了2個(gè)變量i1 和 i2,它們引用到同一個(gè)動(dòng)態(tài)分配的數(shù)組。i1 通過 operator[]() 操作符保存了一個(gè)整數(shù)1——這個(gè)整數(shù)可以被 i2 引用,比如打印到標(biāo)準(zhǔn)輸出。boost::shared_array 也同樣提供了 get() 和 reset() 方法。 另外還重載了 operator bool()。弱指針只有在配合共享指針一起使用時(shí)才有意義。 弱指針 boost::weak_ptr#include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> DWORD WINAPI reset(LPVOID p) boost::shared_ptr<int> *sh =
static_cast<boost::shared_ptr<int>*>(p); DWORD WINAPI print(LPVOID p) boost::weak_ptr<int> *w =
static_cast<boost::weak_ptr<int>*>(p); boost::shared_ptr<int> sh = w->lock(); std::cout << *sh << std::endl; boost::shared_ptr<int> sh(new int(99)); boost::weak_ptr<int> w(sh); threads[0] = CreateThread(0, 0, reset, &sh, 0, 0); threads[1] = CreateThread(0, 0, print, &w, 0, 0); WaitForMultipleObjects(2, threads, TRUE, INFINITE); boost::weak_ptr 必定總是通過 boost::shared_ptr 來初始化的。一旦初始化之后,它基本上只提供一個(gè)有用的方法: lock()。此方法返回的boost::shared_ptr 與用來初始化弱指針的共享指針共享所有權(quán)。
如果這個(gè)共享指針不含有任何對(duì)象,返回的共享指針也將是空的。當(dāng)函數(shù)需要一個(gè)由共享指針?biāo)芾淼膶?duì)象,而這個(gè)對(duì)象的生存期又不依賴于這個(gè)函數(shù)時(shí),就可以使用弱指針。 只要程序中還有一個(gè)共享指針掌管著這個(gè)對(duì)象,函數(shù)就可以使用該對(duì)象。
如果共享指針復(fù)位了,就算函數(shù)里能得到一個(gè)共享指針,對(duì)象也不存在了。上例的 main() 函數(shù)中,通過Windows API 創(chuàng)建了2個(gè)線程。 于是乎,該例只能在Windows 平臺(tái)上編譯運(yùn)行。第一個(gè)線程函數(shù) reset() 的參數(shù)是一個(gè)共享指針的地址。 第二個(gè)線程函數(shù)print() 的參數(shù)是一個(gè)弱指針的地址。 這個(gè)弱指針是之前通過共享指針初始化的。一旦程序啟動(dòng)之后,reset() 和 print()就都開始執(zhí)行了。 不過執(zhí)行順序是不確定的。 這就導(dǎo)致了一個(gè)潛在的問題:reset() 線程在銷毀對(duì)象的時(shí)候print() 線程可能正在訪問它。通過調(diào)用弱指針的 lock() 函數(shù)可以解決這個(gè)問題:如果對(duì)象存在,那么lock() 函數(shù)返回的共享指針指向這個(gè)合法的對(duì)象。否則,返回的共享指針被設(shè)置為0,這等價(jià)于標(biāo)準(zhǔn)的null指針。弱指針本身對(duì)于對(duì)象的生存期沒有任何影響。 lock() 返回一個(gè)共享指針,print() 函數(shù)就可以安全的訪問對(duì)象了。 這就保證了——即使另一個(gè)線程要釋放對(duì)象——由于我們有返回的共享指針,對(duì)象依然存在。介入式指針boost::intrusive_ptr的工作方式和共享指針完全一樣。boost::shared_ptr 在內(nèi)部記錄著引用到某個(gè)對(duì)象的共享指針的數(shù)量,可是對(duì)介入式指針來說,程序員就得自己來做記錄。
對(duì)于框架對(duì)象來說這就特別有用,因?yàn)樗鼈冇涗浿陨肀灰玫拇螖?shù)。#include <boost/intrusive_ptr.hpp> void intrusive_ptr_add_ref(IDispatch *p) void intrusive_ptr_release(IDispatch *p) void check_windows_folder() CLSIDFromProgID(CComBSTR("Scripting.FileSystemObject"),
&clsid); CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, __uuidof(IDispatch),
&p); boost::intrusive_ptr<IDispatch> disp(static_cast<IDispatch*>(p));CComDispatchDriver dd(disp.get()); CComVariant arg("C:\\Windows"); dd.Invoke1(CComBSTR("FolderExists"), &arg, &ret); std::cout << (ret.boolVal != 0) << std::endl; COM 對(duì)象是使用 boost::intrusive_ptr的絕佳范例,因?yàn)?COM 對(duì)象需要記錄當(dāng)前有多少指針引用著它。 通過調(diào)用 AddRef() 和 Release() 函數(shù),內(nèi)部的引用計(jì)數(shù)分別增 1 或者減 1。當(dāng)引用計(jì)數(shù)為 0 時(shí),COM 對(duì)象自動(dòng)銷毀。在 intrusive_ptr_add_ref() 和 intrusive_ptr_release() 內(nèi)部調(diào)用 AddRef() 和Release() 這兩個(gè)函數(shù),來增加或減少相應(yīng) COM 對(duì)象的引用計(jì)數(shù)。#include
<boost/ptr_container/ptr_vector.hpp> boost::ptr_vector<int> v; boost::ptr_vector 專門用于動(dòng)態(tài)分配的對(duì)象,它使用起來更容易也更高效。boost::ptr_vector 獨(dú)占它所包含的對(duì)象,因而容器之外的共享指針不能共享所有權(quán),這跟 std::vector<boost::shared_ptr<int> > 相反。除了 boost::ptr_vector 之外,專門用于管理動(dòng)態(tài)分配對(duì)象的容器還包括:boost::ptr_deque, boost::ptr_list, boost::ptr_set, boost::ptr_map, boost::ptr_unordered_set 和 boost::ptr_unordered_map。這些容器等價(jià)于C++標(biāo)準(zhǔn)里提供的那些。
瀏覽
49
豆花视频一区二区三区在线观看
|
人人澡人人爽人人精品
|
婷婷在线综合激情
|
天天操天天干天天爽
|
青娱乐偷拍视频
|