2010-04-08 114 views
4

我有一個std::listboost::shared_ptr<T>,我想從中刪除一個項目,但我只有一個T *類型的指針,它與列表中的某個項目相匹配。從列表中刪除boost :: shared_ptr的正確方法是什麼?

但是我不能使用myList.remove(tPtr)我猜測是因爲shared_ptr沒有爲其模板參數類型實現==

我的直接想法是嘗試myList.remove(shared_ptr<T>(tPtr))它在語法上是正確的,但它會從雙刪除崩潰,因爲臨時shared_ptr有一個單獨的use_count。

std::list< boost::shared_ptr<T> > myList; 

T* tThisPtr = new T(); // This is wrong; only done for example code. 
         // stand-in for actual code in T using 
         // T's actual "this" pointer from within T 
{ 
    boost::shared_ptr<T> toAdd(tThisPtr); // typically would be new T() 
    myList.push_back(toAdd); 
} 

{ 
    //T has pointer to myList so that upon a certain action, 
    // it will remove itself romt the list 

    //myList.remove(tThisPtr);      //doesn't compile 
    myList.remove(boost::shared_ptr<T>(tThisPtr)); // compiles, but causes 
                // double delete 
} 

我看到剩下的唯一選擇是使用std ::找到通過列表強力的自定義比較,或循環並找到它自己,但它似乎應該有一個更好的辦法。

我是否錯過了一些明顯的東西,或者這太不合標準了嗎?

回答

4

的std ::名單的remove_if成員是你所需要的:

定義謂詞

template <typename T> struct shared_equals_raw 
{ 
    shared_equals_raw(T* raw) 
    :_raw(raw) 
    {} 
    bool operator()(const boost::shared_ptr<T>& ptr) const 
    { 
     return (ptr.get()==_raw); 
    } 
private: 
    T*const _raw; 
}; 

,那麼你可以調用

myList.remove_if(shared_equals_raw(tThisPtr)); 

有列表清理其具有shared_ptrs節點到tThisPtr。

(未經測試,所以也許一些語法的東西需要修復)。

Michael Burr的建議re enable_shared_from_this雖然不錯,最好避免使用原始tThisPtr。

+0

對不起,我不是故意踩你的腳趾,我沒有看到你已經有了解決辦法。 +1表示正確的答案,-0表示不正確的ish語法。 :) – GManNickG 2010-04-08 01:48:18

+3

+1是正確的,但... GAH MY EYES!無法處理奇怪的聲音模式! :) – 2010-04-08 01:48:37

5

你是對的,我們不能直接比較指針。但確實存在remove_if,我們可以指定我們自己的謂詞。解決方案:

template <typename T> 
struct ptr_contains_predicate 
{ 
    ptr_contains_predicate(T* pPtr) : 
    mPtr(pPtr) 
    {} 

    template <typename P> 
    bool operator()(const p& pPtr) const 
    { 
     return pPtr.get() == mPtr; 
    } 

    T* mPtr; 
}; 

template <typename T> 
ptr_contains_predicate<T> ptr_contains(T* pPtr) 
{ 
    return ptr_contains_predicate<T>(pPtr); 
} 

只要將上述謂詞保存在某個標頭中,並且您可以隨時隨地使用它。

myList.remove_if(ptr_contains(tThisPtr)); 

最好的解決辦法是擺在首位從來沒有失去shared_ptr的保持,因此我們可以只使用remove,但上面是無害的反正。

+0

該死的你! (打我一分鐘...)+1 – 2010-04-08 01:45:51

+4

在C++ 0X中不需要函子: myList.remove_if([ptr](shared_ptr p){return p.get()== ptr;}) ; – Asik 2010-12-28 03:29:08

0

您可以使用共享指針將其刪除嗎?

std::list< boost::shared_ptr<T> > myList; 

boost::shared_ptr<T> tThisPtr = new T(); 

{ 
    myList.push_back(tThisPtr); 
} 

{ 
    myList.remove(tThisPtr);      
} 
相關問題