4

我有一个std::listofboost::shared_ptr<T>并且我想从中删除一个项目,但我只有一个 T* 类型的指针,它与列表中的一个项目匹配。

但是我猜我不能使用myList.remove( tPtr ),因为 shared_ptr 没有实现==它的模板参数类型。

我的直接想法是尝试哪个在语法上是正确的,但由于临时有一个单独的 use_count myList.remove( shared_ptr<T>(tPtr) ),它会因双重删除而崩溃。shared_ptr

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::find 与自定义比较一起使用,或者循环遍历列表蛮力并自己找到它,但似乎应该有更好的方法。

我是否遗漏了一些明显的东西,或者这是否太不标准了,不能以清除干净/正常的方式使用?

4

4 回答 4

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,但无论如何以上都是无害的。

于 2010-04-08T01:43:04.247 回答
4

std::list 的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 关于 enable_shared_from_this 的建议虽然很好;最好完全避免使用原始的 tThisPtr 。

于 2010-04-08T01:33:30.503 回答
3

enable_shared_from_this可以帮助您解决问题,但它需要您在列表中使用的类型派生自它:

如果该类型启用该功能,您可以通过调用从对象本身获取共享指针shared_from_this()

于 2010-04-08T01:09:15.020 回答
0

您可以使用共享指针将其删除吗?

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

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

{
    myList.push_back(tThisPtr);
}

{
    myList.remove(tThisPtr);                     
}
于 2010-04-08T03:04:16.880 回答