2014-09-03 50 views
7

我無法理解shared_ptr如何存儲我給它的刪除程序。shared_ptr商店刪除器如何?

最初,使用shared_ptr<int>,我想這可能使用std::function<void(int*)>,但我可以給,因爲有刪除,任何類型的函數(或可調用對象),只要第一個參數是int*

shared_ptr如何做到這一點?

對不起,如果這是一個愚蠢的問題,我是C++的新手,原諒我!

編輯: 問題是:我該怎麼做這樣的事情?我應該使用什麼?任何示例?或者這是一個非常高級的話題?

+1

你想了解你的特殊的編譯器和庫? (如果是這樣,告訴我們你正在使用哪一個)或者C++標準對所有符合實現的說法? – 2014-09-03 23:31:15

+0

我會知道我該怎麼做這樣的事情。我將編輯消息。 – Toccio 2014-09-03 23:32:45

+1

@Toccio:該行爲由模板啓用。這是一個高級話題。這個問題的榮譽,這是合理的,並且很好。 – Jon 2014-09-03 23:36:06

回答

7

刪除程序和分配程序都進行了類型擦除。共享指針管理一個動態分配的私有模板控制對象,通過一個多態基地訪問該控制對象,並存儲所有特定於類型的狀態和功能。

std::function的實現使用了類似的想法,因爲它也是一個刪除類型的動態管理器類,但兩者通常都是完全分開實現的。

結果是兩個班都相對「昂貴」,只有在真正需要時才能使用。否則,更便宜的,非多態的非動態解決方案通常是優選的。

4

我可以給作爲一個刪除器,任何種類的功能(或可調用對象),只要第一個參數是一個int*

不,不是真的。該std::shared_ptr構造具有下列合同,在第20.8.2.2.1([util.smartptr.shared.const])發現:

template<class Y, class D> shared_ptr(Y* p, D d); 
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); 
template <class D> shared_ptr(nullptr_t p, D d); 
template <class D, class A> shared_ptr(nullptr_t p, D d, A a); 

要求:p應轉換爲T*D應爲CopyConstructible。 D的複製構造函數和析構函數不得拋出異常。 表示d(p)的格式良好,應有明確的行爲,不得拋出異常。 A應該是一個分配器(17.6.3.5)。 A的拷貝構造函數和析構函數不得拋出異常。

影響:構造一個擁有對象p和刪除者d的對象。第二和第四個構造函數應使用a的副本分配內存供內部使用。

後續條件:use_count() == 1 && get() == p

拋出:bad_alloc,或當無法獲取內存以外的其他資源時執行定義的異常。

異常安全:如果引發異常,則調用d(p)

這個要求比刪除者的第一個參數必須是正確的類型強得多。它必須是唯一的參數(沒有默認參數),因此d(p)是合法的。這比std::function<void (int*)>稍微靈活一點,因爲返回類型可以是任何東西,但是對於異常保證它也更加受限制。

如果在爲多個必需參數提供刪除程序時,編譯器無法捕捉到您,則標準庫實現正在做一些相當錯誤的事情。

至於如何實現它,利用它必須是CopyConstructible的事實。例如,下面的拉姆達應該工作得很好,並分配給std::function<void(void)>(的拷貝構造保障可確保價值的作品,捕捉):

[d, p] { d(p); } 
+0

@hvd:我說「必須是沒有默認參數的唯一參數」。在你的例子中,它是。 – 2014-09-03 23:42:13

+0

啊,謝謝你清理那個,我誤解了你的答案。 – hvd 2014-09-03 23:43:48

+1

「如果你的編譯器在你提供了一個需要多個參數的刪除器時沒有抓住你,它就會做一些相當錯誤的事情。」不必要。違反*要求*條款導致UB。編譯器不需要診斷它。 – 2014-09-03 23:51:43

相關問題