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則被調用。
(強調使用粗體是我的)。

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銷毀指向的對象。該實現會自動執行此操作。

TA貢獻1812條經驗 獲得超5個贊
只是,
shared_ptr 使用由構造函數創建的特殊刪除函數,該函數始終使用給定對象的析構函數而不是Base的析構函數,這與模板元編程有關,但確實可行。
像這樣
template<typename SomeType>
shared_ptr(SomeType *p)
{
this->destroyer = destroyer_function<SomeType>(p);
...
}
- 3 回答
- 0 關注
- 441 瀏覽
添加回答
舉報