2010-04-08 126 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);      
} 
相关问题