2016-11-07 46 views
0

我需要爲共享指針實例編寫我自己的析構函數。不幸的是,這樣的實例是從庫函數調用中獲得的,並不是我初始化它的。那麼我怎麼能在這裏「設置」析構函數呢?如何爲現有的共享指針設置刪除器?

理想的情況下,在我腦海裏的代碼可能看起來像

pointer.setDeleter(myDeleter); 

pointer = std::make_shared<MyType>(pointerOld.get(), myDeleter); 

我沒有找到的第一個假設的API。對於第二個,據說MyType沒有帶2個參數的構造函數。它不可編譯。

對此有何想法?

謝謝!

+0

爲什麼你想要這個?據推測,圖書館不希望你與他們的刪除者搞砸。 – GManNickG

+0

@GManNickG因爲我正在使用具有事件庫機制的庫。因此,我希望在某個線程(即事件庫的線程)中調用刪除器。否則,刪除者將引入段錯誤。 – zzy

+0

您是否需要在釋放對共享指針的最後一個引用時調用刪除器,或者是否足以創建一個新的共享指針(具有其自己的生存期),該共享指針延長了源共享指針的生命週期,去零,運行額外的代碼? – Yakk

回答

1

這是我能得到的最接近的。

template<class T> 
std::shared_ptr<T> extra_deleter(std::shared_ptr<T> in, std::function<void(T*)> action) { 
    if (!in) return {}; 
    if (!action) return std::move(in); 
    // action=std::move(action) in c++14 
    auto new_deleter = [action](std::shared_ptr<T>* tin) { 
     action(tin->get()); 
     delete tin; 
    }; 

    auto tmp = std::shared_ptr<std::shared_ptr<T>>(
    new shared_ptr<T>(std::move(in)), 
    std::move(new_deleter) 
); 
    if (!tmp) return {}; 
    // aliasing ctor: 
    return {tmp, tmp.get()->get()}; 
} 

此創建一個共享指針共享指針,以定製刪除動作增強它,然後使用別名構造函數創建一個共享的指針T.

這不會導致額外的代碼運行時來源shared_ptr被銷燬。相反,它會創建一個新的shared_ptr,其中包含額外的銷燬代碼。當新的血統shared_ptr死亡時,運行action

如果沒有其他原始shared_ptr狀態的其他引用,則運行shared_ptr的原始驅逐程序。

+0

對不起,我沒有完全明白你的想法 - 我對C++ 11相對來說比較陌生。你能告訴我如何調用這個函數(特別是當刪除器是一個類的非靜態成員函數時(實際上所有這些東西都在一個類中))?另外,我不理解最後的返回語句:爲什麼我們在** curly **括號中有這兩個參數? – zzy

+0

@zzy傳遞一個lambda的'T *'作爲'action',就像'[](T * foo){std :: cout <<(void *)foo <<'\ n';}'打印指針值。作爲第一個參數傳遞'shared_ptr '。它返回一個擴充的共享ptr,當它的引用計數到期時,它會調用該操作。然後它放棄源shared_ptr上的引用計數。它仍然指向相同的「T」。 'return {a,b};'是用'a,b'直接調用返回值的ctor的方法。原始的共享ptr狀態不會被修改。 – Yakk