3 回答

TA貢獻(xiàn)1794條經(jīng)驗(yàn) 獲得超8個(gè)贊
智能指針的基本屬性
當(dāng)您擁有可以分配每個(gè)智能指針的屬性時(shí),這很容易。有三個(gè)重要的屬性。
根本沒(méi)有所有權(quán)
所有權(quán)轉(zhuǎn)讓
所有權(quán)份額
第一個(gè)意味著智能指針不能刪除對(duì)象,因?yàn)樗粨碛兴?。第二個(gè)意味著只有一個(gè)智能指針可以同時(shí)指向同一個(gè)對(duì)象。如果要從函數(shù)返回智能指針,則所有權(quán)將轉(zhuǎn)移到返回的智能指針。
第三個(gè)意味著多個(gè)智能指針可以同時(shí)指向同一個(gè)對(duì)象。這也適用于原始指針,但原始指針缺少一個(gè)重要特征:它們不定義它們是否擁有。如果每個(gè)所有者放棄該對(duì)象,則共享所有權(quán)智能指針將刪除該對(duì)象。這種行為恰好經(jīng)常需要,因此共享?yè)碛械闹悄苤羔槒V泛傳播。
一些擁有智能指針既不支持第二個(gè)也不支持第三個(gè)。因此,它們不能從函數(shù)返回或傳遞到其他地方。哪個(gè)最適合RAII
智能指針保持在本地并且剛剛創(chuàng)建的目的,以便在超出范圍后釋放對(duì)象。
可以通過(guò)擁有復(fù)制構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)所有權(quán)共享。這自然會(huì)復(fù)制一個(gè)智能指針,副本和原始文件都將引用同一個(gè)對(duì)象。所有權(quán)的轉(zhuǎn)移當(dāng)前并不能真正用C ++實(shí)現(xiàn),因?yàn)闆](méi)有辦法將某些東西從一個(gè)對(duì)象轉(zhuǎn)移到另一個(gè)對(duì)象支持的語(yǔ)言:如果你試圖從一個(gè)函數(shù)返回一個(gè)對(duì)象,那么正在發(fā)生的事情是該對(duì)象被復(fù)制。因此,實(shí)現(xiàn)所有權(quán)轉(zhuǎn)移的智能指針必須使用復(fù)制構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)所有權(quán)的轉(zhuǎn)移。然而,這反過(guò)來(lái)又破壞了它在容器中的使用,因?yàn)樾枨舐暶髁巳萜髟氐膹?fù)制構(gòu)造函數(shù)的某種行為,這與這些智能指針的所謂“移動(dòng)構(gòu)造函數(shù)”行為不相容。
C ++ 1x通過(guò)引入所謂的“移動(dòng)構(gòu)造函數(shù)”和“移動(dòng)賦值運(yùn)算符”為所有權(quán)轉(zhuǎn)移提供本機(jī)支持。它還附帶了一個(gè)名為的所有權(quán)轉(zhuǎn)移智能指針unique_ptr
。
分類智能指針
scoped_ptr
是一個(gè)既不可轉(zhuǎn)移也不可共享的智能指針。它只是在本地需要分配內(nèi)存時(shí)才可用,但是當(dāng)它超出范圍時(shí)確保它再次被釋放。但如果您愿意,它仍然可以與另一個(gè)scoped_ptr交換。
shared_ptr
是一個(gè)共享所有權(quán)的智能指針(上面第三種)。它是引用計(jì)數(shù),因此它可以看到它的最后一個(gè)副本超出范圍,然后釋放所管理的對(duì)象。
weak_ptr
是一個(gè)非擁有的智能指針。它用于引用托管對(duì)象(由shared_ptr管理),而不添加引用計(jì)數(shù)。通常,您需要從shared_ptr中獲取原始指針并復(fù)制它。但這不安全,因?yàn)槟銦o(wú)法檢查對(duì)象何時(shí)被實(shí)際刪除。因此,weak_ptr通過(guò)引用shared_ptr管理的對(duì)象來(lái)提供方法。如果您需要訪問(wèn)該對(duì)象,您可以鎖定它的管理(以避免在另一個(gè)線程中,shared_ptr在您使用該對(duì)象時(shí)釋放它)然后使用它。如果weak_ptr指向已刪除的對(duì)象,它將通過(guò)拋出異常來(lái)通知您。當(dāng)你有一個(gè)循環(huán)引用時(shí),使用weak_ptr是最有益的:引用計(jì)數(shù)不能輕易應(yīng)對(duì)這種情況。
intrusive_ptr
就像shared_ptr一樣,但它不會(huì)將引用計(jì)數(shù)保留在shared_ptr中,而是將計(jì)數(shù)遞增/遞減到需要由托管對(duì)象定義的某些輔助函數(shù)。這樣做的好處是,已經(jīng)引用的對(duì)象(具有由外部引用計(jì)數(shù)機(jī)制遞增的引用計(jì)數(shù))可以填充到intrusive_ptr中 - 因?yàn)橐糜?jì)數(shù)不再是智能指針的內(nèi)部,但智能指針使用現(xiàn)有的參考計(jì)數(shù)機(jī)制。
unique_ptr
是所有權(quán)指針的轉(zhuǎn)移。你無(wú)法復(fù)制它,但你可以使用C ++ 1x的移動(dòng)構(gòu)造函數(shù)來(lái)移動(dòng)它:
unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!
這是std :: auto_ptr遵循的語(yǔ)義,但由于缺少對(duì)移動(dòng)的本機(jī)支持,它無(wú)法提供它們而沒(méi)有陷阱。unique_ptr將自動(dòng)從臨時(shí)的其他unique_ptr中竊取資源,這是移動(dòng)語(yǔ)義的關(guān)鍵特性之一。auto_ptr將在下一個(gè)C ++標(biāo)準(zhǔn)版本中棄用,而不是unique_ptr。C ++ 1x還允許填充僅可移動(dòng)但不可復(fù)制到容器中的對(duì)象。因此,您可以將unique_ptr填充到矢量中。如果你想了解更多相關(guān)信息,我會(huì)在這里停下來(lái)并引用你一篇關(guān)于此的精彩文章。

TA貢獻(xiàn)1783條經(jīng)驗(yàn) 獲得超4個(gè)贊
scoped_ptr是最簡(jiǎn)單的。當(dāng)它超出范圍時(shí),它就會(huì)被銷毀。以下代碼是非法的(scoped_ptrs是不可復(fù)制的),但將說(shuō)明一點(diǎn):
std::vector< scoped_ptr<T> > tPtrVec;{ scoped_ptr<T> tPtr(new T()); tPtrVec.push_back(tPtr); // raw T* is freed}tPtrVec[0]->DoSomething(); // accessing freed memory
shared_ptr是引用計(jì)數(shù)。每次發(fā)生復(fù)制或分配時(shí),引用計(jì)數(shù)都會(huì)遞增。每次觸發(fā)實(shí)例的析構(gòu)函數(shù)時(shí),原始T *的引用計(jì)數(shù)都會(huì)遞減。一旦為0,指針就被釋放。
std::vector< shared_ptr<T> > tPtrVec;{ shared_ptr<T> tPtr(new T()); // This copy to tPtrVec.push_back and ultimately to the vector storage // causes the reference count to go from 1->2 tPtrVec.push_back(tPtr); // num references to T goes from 2->1 on the destruction of tPtr}tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe
weak_ptr是對(duì)共享指針的弱引用,需要您檢查指向的shared_ptr是否仍然存在
std::vector< weak_ptr<T> > tPtrVec;{ shared_ptr<T> tPtr(new T()); tPtrVec.push_back(tPtr); // num references to T goes from 1->0}shared_ptr<T> tPtrAccessed = tPtrVec[0].lock();if (tPtrAccessed[0].get() == 0){ cout << "Raw T* was freed, can't access it"}else{ tPtrVec[0]->DoSomething(); // raw }
當(dāng)您必須使用第三方智能ptr時(shí),通常會(huì)使用intrusive_ptr。它將調(diào)用一個(gè)自由函數(shù)來(lái)添加和減少引用計(jì)數(shù)。請(qǐng)參閱提升文檔的鏈接以獲取更多信息。

TA貢獻(xiàn)1820條經(jīng)驗(yàn) 獲得超3個(gè)贊
不要忽視boost::ptr_container
任何有關(guān)boost智能指針的調(diào)查。在例如std::vector<boost::shared_ptr<T> >
太慢的情況下,它們可能是非常寶貴的。
- 3 回答
- 0 關(guān)注
- 571 瀏覽
添加回答
舉報(bào)