亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

shared_ptr魔術:)

shared_ptr魔術:)

C++
揚帆大魚 2019-10-06 13:11:15
Lidstr?m先生的主張是,構造shared_ptr<Base> p(new Derived);不需要Base具有虛擬析構函數:Armen Tsirunyan:“真的嗎?shared_ptr會正確清理嗎?在這種情況下,請您演示一下如何實現這種效果?”DanielLidstr?m:“ shared_ptr使用其自己的析構函數來刪除具體實例。在C ++社區中,這被稱為RAII。我的建議是,您將學習到有關RAII的全部知識。它將使您使用C ++的代碼如此容易在任何情況下都可以使用RAII。”Armen Tsirunyan:“我了解RAII,而且我也知道,最終pn到達0時,shared_ptr析構函數可能會刪除存儲的px。但是,如果px具有指向的靜態類型指針Base和動態類型的指針Derived,則除非Base具有虛擬析構函數,否則會導致不確定的行為。如果我做錯了,請糾正我。”DanielLidstr?m:“ shared_ptr知道靜態類型是Concrete。自從我在其構造函數中傳遞它以來,它就知道這一點!看起來有點像魔術,但是我可以向您保證,它是設計使然,非常好?!彼?,判斷我們。在不要求多態類具有虛擬析構函數的情況下,如何(如果可能)實現shared_ptr?提前致謝
查看完整描述

3 回答

?
達令說

TA貢獻1821條經驗 獲得超6個贊

是的,可以通過這種方式實現shared_ptr。Boost確實如此,并且C ++ 11標準也需要這種行為。作為一種附加的靈活性,shared_ptr不僅可以管理引用計數器。通常將所謂的刪除器放入還包含引用計數器的同一存儲塊中。但有趣的是,此刪除器的類型不是shared_ptr類型的一部分。這稱為“類型擦除”,基本上與用于實現“多態函數” boost :: function或std :: function的技術相同,用于隱藏實際的仿函數的類型。為了使您的示例正常工作,我們需要一個模板化的構造函數:


template<class T>

class shared_ptr

{

public:

   ...

   template<class Y>

   explicit shared_ptr(Y* p);

   ...

};

因此,如果您將其與Base和Derived類一起使用,則...


class Base {};

class Derived : public Base {};


int main() {

   shared_ptr<Base> sp (new Derived);

}

...具有Y = Derived的模板化構造函數用于構造shared_ptr對象。因此,構造函數有機會創建適當的刪除對象和引用計數器,并將指向該控制塊的指針存儲為數據成員。如果參考計數器達到零,則將使用先前創建的可感知派生的刪除器來處置該對象。


關于此構造函數(20.7.2.2.1),C ++ 11標準具有以下說法:


要求: p必須可轉換為T*。Y應為完整類型。該表達式delete p應格式正確,行為應明確,并且不得拋出異常。


效果:構造一個shared_ptr對象是擁有指針p。



對于析構函數(20.7.2.2.2):


效果:如果*this為空或與另一個shared_ptr實例(use_count() > 1)共享所有權,則沒有副作用。否則,如果*this擁有一個對象p和一個deleteer d,d(p)則被調用。 否則,如果*this擁有一個指針p,delete p則被調用。


(強調使用粗體是我的)。


查看完整回答
反對 回復 2019-10-06
?
喵喵時光機

TA貢獻1846條經驗 獲得超7個贊

創建shared_ptr時,它將在內部存儲一個刪除程序對象。當shared_ptr將要釋放所指向的資源時,將調用此對象。由于您知道如何在構造時銷毀資源,因此可以對不完整的類型使用shared_ptr。誰創建了shared_ptr,誰在其中存儲了正確的刪除器。


例如,您可以創建一個自定義刪除器:


void DeleteDerived(Derived* d) { delete d; } // EDIT: no conversion needed.


shared_ptr<Base> p(new Derived, DeleteDerived);

p將調用DeleteDerived銷毀指向的對象。該實現會自動執行此操作。


查看完整回答
反對 回復 2019-10-06
?
ABOUTYOU

TA貢獻1812條經驗 獲得超5個贊

只是,


shared_ptr 使用由構造函數創建的特殊刪除函數,該函數始終使用給定對象的析構函數而不是Base的析構函數,這與模板元編程有關,但確實可行。


像這樣


template<typename SomeType>

shared_ptr(SomeType *p)

{

   this->destroyer = destroyer_function<SomeType>(p);

   ...

}


查看完整回答
反對 回復 2019-10-06
  • 3 回答
  • 0 關注
  • 441 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號