久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Boost中的智能指針--BoostProgrammSmartPoint

 Gemmy 2007-05-31

Boost中的智能指針

撰文 Bjorn Karlsson 翻譯 曾毅 最后更新:2004年6月2日 歡迎來到Boost,C++革新者出類拔萃的社群。如果你在C++標(biāo)準(zhǔn)庫(kù)當(dāng)中找不到你所需要的,,很可能Boost已經(jīng)為您準(zhǔn)備好了他們的產(chǎn)品,。

根據(jù)Boost網(wǎng)站的介紹,Boost是“一個(gè)免費(fèi)的,可移植的,,同步評(píng)測(cè)的C++庫(kù),,Boost堪稱是新類庫(kù)的典范,特別是其中那些能夠與ISO C++標(biāo)準(zhǔn)庫(kù)良好的協(xié)同工作的庫(kù)。”但是Boost不僅僅是一個(gè)庫(kù)的集合,。它也是一個(gè)快速發(fā)展的開發(fā)者社區(qū),,這些開發(fā)者創(chuàng)建,使用以及參與討論Boost 庫(kù),。Boost社群不僅僅是維護(hù)著這個(gè)庫(kù),,而且還為它的使用者和設(shè)計(jì)者提供學(xué)習(xí)交流的場(chǎng)所。這個(gè)庫(kù)堪稱是一個(gè)設(shè)計(jì)穩(wěn)固類的精典范例,,在下個(gè)版本發(fā)布之前你 甚至感覺不到能夠有什么地方還值得改進(jìn),。加入Boost郵件列表上的討論組(或者是活躍于其中,或者只是看看別人如何討論)是提高你對(duì)庫(kù)的設(shè)計(jì)的問題和解 決方案的認(rèn)識(shí)的非常好的方法,。Boost還提供一個(gè)人數(shù)飛速增長(zhǎng)的Boost使用者郵件列表,,這個(gè)列表關(guān)注的內(nèi)容集中在使用Boost庫(kù)的問題上。 Boost庫(kù)的質(zhì)量和他的技術(shù)標(biāo)準(zhǔn)是十分令人驚異的,。Boost可移植性標(biāo)準(zhǔn)確保了當(dāng)你將你的代碼從一個(gè)平臺(tái)上移動(dòng)到另一個(gè)平臺(tái)上時(shí),,你的庫(kù)仍然會(huì)正常工 作。最近的發(fā)布版本是Boost 1.25.0,,由從智能指針到正則表達(dá)式,,直至可移植的線程庫(kù)。Boost目前支持35個(gè)庫(kù),,這些當(dāng)中所有的內(nèi)容都被社區(qū)的成員測(cè)試和使用過了,。這些庫(kù)都 是可以免費(fèi)使用的,它們當(dāng)中的很多內(nèi)容都已經(jīng)被用于商業(yè)應(yīng)用軟件的開發(fā),。

Boost是C++社群中最為強(qiáng)大的一個(gè)之一,。在2000名成員當(dāng)中,很多的人都是世界頂級(jí)的C++程序員,。這些成員之所以能夠長(zhǎng)期的參與到其中 來是因?yàn)樗麄兎浅釔弁瑩碛凶顑?yōu)秀的思維方法的程序設(shè)計(jì)者一同工作,。他們同時(shí)很清楚他們的努力必定會(huì)對(duì)C++社群產(chǎn)生巨大的影響,因?yàn)槟阍贐oost當(dāng)中 看到的大部分內(nèi)容將成為融入未來C++標(biāo)準(zhǔn)的候選內(nèi)容,。

了解Boost最好的方法就是瀏覽Boost庫(kù),。在這篇文章當(dāng)中,我將向你介紹Boost的智能指針(smart pointer)庫(kù)smart_ptr,。smart_ptr是一個(gè)能夠反映出Boost的創(chuàng)新以及完美設(shè)計(jì)的好例子,。我建議你訪問Boost的站點(diǎn)()來 獲取Boost集中的其它34個(gè)庫(kù)的詳細(xì)內(nèi)容。

相對(duì)來說比較小的Boost庫(kù)之一便是smart_ptr,。smart_ptr是我認(rèn)為在C++標(biāo)準(zhǔn)中將會(huì)停止向前發(fā)展的庫(kù)之一,。這篇文章討論了Boost當(dāng)中的smart_ptr庫(kù)。但首先,我將以一個(gè)對(duì)智能指針的簡(jiǎn)介開始,。

智能指針的30秒介紹

智能指針是存儲(chǔ)指向動(dòng)態(tài)分配(堆)對(duì)象指針的類,。除了能夠在適當(dāng)?shù)臅r(shí)間自動(dòng)刪除指向的對(duì)象外,他們的工作機(jī)制很像C++的內(nèi)置指針,。智能指針在面對(duì)異常的時(shí)候格外有用,,因?yàn)樗麄兡軌虼_保正確的銷毀動(dòng)態(tài)分配的對(duì)象。他們也可以用于跟蹤被多用戶共享的動(dòng)態(tài)分配對(duì)象,。

事實(shí)上,,智能指針能夠做的還有很多事情,例如處理線程安全,,提供寫時(shí)復(fù)制,,確保協(xié)議,并且提供遠(yuǎn)程交互服務(wù),。有能夠?yàn)檫@些ESP (Extremely Smart Pointers)創(chuàng)建一般智能指針的方法,,但是并沒有涵蓋近來。(可以查看[1]來了解關(guān)于這個(gè)主題的更為深入的內(nèi)容,,順便提一下,, Alexandrescu現(xiàn)在正在考慮將他的C++庫(kù)Loki提交給Boost)。

智能指針的大部分使用是用于生存期控制,,階段控制,。它們使用operator->和operator*來生成原始指針,這樣智能指針看上去就像一個(gè)普通指針,。

這樣的一個(gè)類來自標(biāo)準(zhǔn)庫(kù):std::auto_ptr,。它是為解決資源所有權(quán)問題設(shè)計(jì)的,但是缺少對(duì)引用數(shù)和數(shù)組的支持,。并且,,std:: auto_ptr在被復(fù)制的時(shí)候會(huì)傳輸所有權(quán)。在大多數(shù)情況下,,你需要更多的和/或者是不同的功能,。這時(shí)就需要加入smart_ptr類。

smart_ptr 類

在Boost中的智能指針有:

,。scoped_ptr,,用于處理單個(gè)對(duì)象的唯一所有權(quán);與std::auto_ptr不同的是,,scoped_ptr可以被復(fù)制,。

。scoped_array,,與scoped_ptr類似,,但是用來處理數(shù)組的

。shared_ptr,,允許共享對(duì)象所有權(quán)

,。shared_array,允許共享數(shù)組所有權(quán)

scoped_ptr
scoped_ptr智能指針與std:: auto_ptr不同,,因?yàn)樗遣粋鬟f所有權(quán)的,。事實(shí)上它明確禁止任何想要這樣做的企圖!這在你需要確保指針任何時(shí)候只有一個(gè)擁有者時(shí)的任何一種情境下都 是非常重要的,。如果不去使用scoped_ptr,,你可能傾向于使用std::auto_ptr,讓我們先看看下面的代碼:

auto_ptr MyOwnString?

(new string("This is mine to keep!"));

auto_ptr NoItsMine?(MyOwnString?);

cout << *MyOwnString << endl; // Boom

這段代碼顯然將不能編譯通過,,因?yàn)樽址乃袡?quán)被傳給了NoItsMine,。這不是std::auto_ptr的設(shè)計(jì)缺陷—而是一個(gè)特性。盡管如此,,當(dāng)你需要MyOwnString達(dá)到上面的代碼預(yù)期的工作效果的話,,你可以使用scoped_ptr:

scoped_ptr MyOwnString?

(new string("This is mine to keep for real!"));

// Compiler error - there is no copy constructor.

scoped_ptr TryingToTakeItAnyway?

(MyOwnString?);

scoped_ptr通過從boost::noncopyable繼承來完成這個(gè)行為(可以查看Boost.utility庫(kù))。不可復(fù)制類聲明復(fù)制構(gòu)造函數(shù)并將賦值操作符聲明為private類型,。

scoped_array
scoped_array與scoped_ptr顯然是意義等價(jià)的,,但是是用來處理數(shù)組的。在這一點(diǎn)標(biāo)準(zhǔn)庫(kù)并沒有考慮—除非你當(dāng)然可以使用std::vector,,在大多數(shù)情況下這樣做是可以的,。

用法和scoped_ptr類似:

typedef tuples::tupleint> ArrayTuple?;

scoped_array MyArray?(new ArrayTuple?[10]);

tuples::get<0>(MyArray?[5]) ="The library Tuples is also part of Boost";

tuple是元素的集合—例如兩倍,三倍,,和四倍,。Tuple的典型用法是從函數(shù)返回多個(gè)值。Boost Tuple庫(kù)可以被認(rèn)為是標(biāo)準(zhǔn)庫(kù)兩倍的擴(kuò)展,,目前它與近10個(gè)tuple元素一起工作,。支持tuple流,比較,,賦值,,卸包等等。更多關(guān)于Boost的 Tuple庫(kù)的信息請(qǐng)參考[2]和[3],。

當(dāng)scoped_array越界的時(shí)候,,delete[]將被正確的調(diào)用。這就避免了一個(gè)常見錯(cuò)誤,,即是調(diào)用錯(cuò)誤的操作符delete,。

shared_ptr
這里有一個(gè)你在標(biāo)準(zhǔn)庫(kù)中找不到的—引用數(shù)智能指 針。大部分人都應(yīng)當(dāng)有過使用智能指針的經(jīng)歷,,并且已經(jīng)有很多關(guān)于引用數(shù)的文章,。最重要的一個(gè)細(xì)節(jié)是引用數(shù)是如何被執(zhí)行的—插入,,意思是說你將引用計(jì)數(shù)的功 能添加給類,或者是非插入,,意思是說你不這樣做,。Boost shared_ptr是非插入類型的,這個(gè)實(shí)現(xiàn)使用一個(gè)從堆中分配來的引用計(jì)數(shù)器,。關(guān)于提供參數(shù)化策略使得對(duì)任何情況都極為適合的討論很多了,,但是最終討 論的結(jié)果是決定反對(duì)聚焦于可用性??墒遣灰竿懻摰慕Y(jié)果能夠結(jié)束,。

shared_ptr完成了你所希望的工作:他負(fù)責(zé)在不使用實(shí)例時(shí)刪除由它指向的對(duì)象(pointee),并且它可以自由的共享它指向的對(duì)象(pointee),。

void PrintIfString?(const any& Any) {

if (const shared_ptr* s =

any_cast >(&Any)) {

cout << **s << endl;

}

}

int main(int argc, char* argv[])

{

std::vector Stuff;

shared_ptr SharedString1?

(new string("Share me. By the way,

Boost.any is another useful Boost

library"));

shared_ptr SharedString2?

(SharedString1?);

shared_ptr SharedInt1?

(new int(42));

shared_ptr SharedInt2?

(SharedInt1?);

Stuff.push_back(SharedString1?);

Stuff.push_back(SharedString2?);

Stuff.push_back(SharedInt1?);

Stuff.push_back(SharedInt2?);

// Print the strings

for_each(Stuff.begin(), Stuff.end(),

PrintIfString?);

Stuff.clear();

// The pointees of the shared_ptr‘s

// will be released on leaving scope

// shared_ptr的pointee離開這個(gè)范圍后將被釋放

return 0;

}

any庫(kù)提供了存儲(chǔ)所有東西的方法[2]HYPERLINK "file:///C:Documents%20and%20SettingsAdministrator桌面 My%20Documents新建 CUJhtml20.04karlsson%22%20l"[4],。在包含類型中需要的是它們是可拷貝構(gòu)造的(CopyConstructible),析 構(gòu)函數(shù)這里絕對(duì)不能引發(fā),,他們應(yīng)當(dāng)是可賦值的,。我們?nèi)绾未鎯?chǔ)和傳遞“所有事物”?無區(qū)別類型(讀作void*)可以涉及到所有的事物,,但這將意味著將類型 安全(與知識(shí))拋之腦后,。any庫(kù)提供類型安全。所有滿足any需求的類型都能夠被賦值,,但是解開的時(shí)候需要知道解開類型,。any_cast是解開由 any保存著的值的鑰匙,any_cast與dynamic_cast的工作機(jī)制是類似的—指針類型的類型轉(zhuǎn)換通過返回一個(gè)空指針成功或者失敗,,因此賦值 類型的類型轉(zhuǎn)換拋出一個(gè)異常(bad_any_cast)而失敗,。

shared_array
shared_array與shared_ptr作用是相同的,只是它是用于處理數(shù)組的,。

shared_array MyStrings?( new Base[20] );

深入shared_ptr實(shí)現(xiàn)

創(chuàng)建一個(gè)簡(jiǎn)單的智能指針是非常容易的,。但是創(chuàng)建一個(gè)能夠在大多數(shù)編譯器下通過的智能指針就有些難度了。而創(chuàng)建同時(shí)又考慮異常安全就更為困難了,。 Boost::shared_ptr這些全都做到了,,下面便是它如何做到這一切的。(請(qǐng)注意:所有的include,,斷開編譯器處理,,以及這個(gè)實(shí)現(xiàn)的部分 內(nèi)容被省略掉了,但你可以在Boost.smart_ptr當(dāng)中找到它們),。

首先,,類的定義:很顯然,智能指針是(幾乎總是)模板,。

template class shared_ptr {

公共接口是:

explicit shared_ptr(T* p =0) : px(p) {

// fix: prevent leak if new throws

try { pn = new long(1); }

catch (...) { checked_delete(p); throw; }

}

現(xiàn)在看來,,在構(gòu)造函數(shù)當(dāng)中兩件事情是容易被忽略的,。構(gòu)造函數(shù)是explicit的,就像大多數(shù)的構(gòu)造函數(shù)一樣可以帶有一個(gè)參數(shù),。另外一個(gè)值 得注意的是引用數(shù)的堆分配是由一個(gè)try-catch塊保護(hù)的,。如果沒有這個(gè),你得到的將是一個(gè)有缺陷的智能指針,,如果引用數(shù)沒有能夠成功分配,,它將不能 正常完成它自己的工作,。

~shared_ptr() { dispose(); }

析構(gòu)函數(shù)執(zhí)行另外一個(gè)重要任務(wù):如果引用數(shù)下降到零,,它應(yīng)當(dāng)能夠安全的刪除指向的對(duì)象(pointee)。析構(gòu)函數(shù)將這個(gè)重要任務(wù)委托給了另外一個(gè)方法:dispose,。

void dispose() { if (—*pn == 0)

{ checked_delete(px); delete pn; } }

正如你所看到的,,引用數(shù)(pn)在減少。如果它減少到零,,checked_delete在所指對(duì)象 (px)上被調(diào)用,,而后引用數(shù)(pn)也被刪除了。

那么,,checked_delete執(zhí)行什么功能呢,?這個(gè)便捷的函數(shù)(你可以在Boost.utility中找到)確保指針代表的是一個(gè)完整的類型。在你的智能指針類當(dāng)中有這個(gè)么,?

這是第一個(gè)賦值運(yùn)算符:

template shared_ptr& operator=

(const shared_ptr& r) {

share(r.px,r.pn);

return *this;

}

這是成員模版,如果不是這樣,,有兩種情況:

1. 如果沒有參數(shù)化復(fù)制構(gòu)造函數(shù),類型賦值Base = Derived無效,。

2. 如果有參數(shù)化復(fù)制構(gòu)造函數(shù),,類型賦值將生效,但同時(shí)創(chuàng)建了一個(gè)不必要的臨時(shí)smart_ptr,。

這再一次的展示給你為什么不應(yīng)當(dāng)加入你自己的智能指針的一個(gè)非常好的原因—這些都不是很明顯的問題,。

賦值運(yùn)算符的實(shí)際工作是由share函數(shù)完成的:

void share(T* rpx, long* rpn) {

if (pn = rpn) { // Q: why not px = rpx?

// A: fails when both == 0

++*rpn; // done before dispose() in case

// rpn transitively dependent on

// *this (bug reported by Ken Johnson)

dispose();

px = rpx;

pn = rpn;

}

}

需要注意的是自我賦值(更準(zhǔn)確地說是自我共享)是通過比較引用數(shù)完成的,而不是通過指針,。為什么這樣呢,?因?yàn)樗鼈儍烧叨伎梢允橇悖灰欢ㄊ且粯拥摹?

template shared_ptr

(const shared_ptr& r) : px(r.px) { // never throws

++*(pn = r.pn);

}

這個(gè)版本是一個(gè)模版化的拷貝構(gòu)造和函數(shù),??梢钥纯瓷厦娴挠懻搧砹私鉃槭裁匆@樣做。

賦值運(yùn)算符以及賦值構(gòu)造函數(shù)在這里同樣也有一個(gè)非模版化的版本:

shared_ptr(const shared_ptr& r) :

// never throws

px(r.px) { ++*(pn = r.pn); }

shared_ptr& operator=

(const shared_ptr& r) {

share(r.px,r.pn);

return *this;

}

reset函數(shù)就像他的名字那樣,,重新設(shè)置所指對(duì)象(pointee),。在將要離開作用域的時(shí)候,如果你需要銷毀所指對(duì)象(pointee)它將非常方便的幫你完成,,或者簡(jiǎn)單的使緩存中的值失效,。

void reset(T* p=0) {

// fix: self-assignment safe

if ( px == p ) return;

if (—*pn == 0)

{ checked_delete(px); }

else { // allocate new reference

// counter

// fix: prevent leak if new throws

try { pn = new long; }

catch (...) {

// undo effect of —*pn above to

// meet effects guarantee

++*pn;

checked_delete(p);

throw;

} // catch

} // allocate new reference counter

*pn = 1;

px = p;

} // reset

這里仍然請(qǐng)注意避免潛在的內(nèi)存泄漏問題和保持異常安全的處理手段,。

這樣你就有了使得智能指針發(fā)揮其“智能”的運(yùn)算符:

// never throws

T& operator*() const { return *px; }

// never throws

T* operator->() const { return px; }

// never throws

T* get() const { return px; }

這僅僅是一個(gè)注釋:有的智能指針實(shí)現(xiàn)從類型轉(zhuǎn)換運(yùn)算符到T*的轉(zhuǎn)換。這不是一個(gè)好主意,,這樣做常會(huì)使你因此受到傷害,。雖然get在這里看上去很不舒服,但它阻止了編譯器同你玩游戲,。

我記得是Andrei Alexandrescu說的:“如果你的智能指針工作起來和啞指針沒什么兩樣,,那它就是啞指針。”簡(jiǎn)直是太對(duì)了,。

這里有一些非常好的函數(shù),,我們就拿它們來作為本文的結(jié)束吧。

long use_count() const

{ return *pn; } // never throws

bool unique() const

{ return *pn == 1; } // never throws

函數(shù)的名字已經(jīng)說明了它的功能了,,對(duì)么,?

關(guān)于Boost.smart_ptr還有很多應(yīng)當(dāng)說明的(比如std::swap和std::less的特化,與std:: auto_ptr榜定在一起確保兼容性以及便捷性的成員,,等等),,由于篇幅限制不能再繼續(xù)介紹了。詳細(xì)內(nèi)容請(qǐng)參考Boost distribution ()的smart_ptr.hpp,。即使沒有那些其它的內(nèi)容,,你不認(rèn)為他的確是一個(gè)非常智能的指針么?

總結(jié)

這僅僅是Boost世界的一個(gè)簡(jiǎn)短的介紹,。歡迎每一個(gè)人的加入,,坦率地說,我認(rèn)為 大多數(shù)的C++程序員有很好的理由這樣做,。我在這里要對(duì)Beman Dawes, David Abrahams, 以及Jens Maurer回答問題以及分享他們觀點(diǎn)的幫助表示感謝(參見“ 來自 Boost創(chuàng)始人的回答 ” ),。

Boost見!

注釋與參考

[1] Andrei Alexandrescu. Modern C++ Design (Addison-Wesley, 2001).

[2] Boost, .

[3] Jaako Jarvi. “Tuple Types and Multiple Return Values,” C/C++ Users Journal, August 2001.

[4] Jim Hyslop和Herb Sutter. “I‘d Hold Anything for You,” C/C++ Users Journal C++ Experts Forum, December 2001, .

[5] Boost郵件列表, .

[6] Boost用戶郵件列表, .

[7] C++ Standard, International Standard ISO/IEC 14882.

作者簡(jiǎn)介 Bjorn Karlsson是ReadSoft專業(yè)的軟件開發(fā)者,您可以通過下面的郵件與他取得聯(lián)系:

[email protected].

譯者注

[1]截至本文翻譯結(jié)束,,Boost社群發(fā)布的最新版本為Boost 1.31.0版,,最新的版本發(fā)布信息可以通過下列地址了解:

http://lists./MailArchives/boost-announce/msg00034.php

http:///project/shownotes.php?release_id=214915

同時(shí)可以通過下面的地址下載所有的Boost發(fā)布版本:

http:///project/showfiles.php?group_id=7586

[2]截至本文翻譯結(jié)束,Boost庫(kù)已經(jīng)擴(kuò)展到了55個(gè),,所有的庫(kù)文檔及其它資源可以通過下列地址獲得:

http://boost./libs/libraries.htm

[3]文中結(jié)尾處提到的“來自 Boost創(chuàng)始人的回答 ” 可以在下面的地址找到:

http://www./documents/s=8470/cuj0204karlsson/side1.htm


  • Set MYTITLE = Boost中的智能指針

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多