我有一个std::list
boost::shared_ptr<T>
我希望从中移除一个项目,但我只有一个T *类型的指针,它与列表中的一个项目相匹配。
但我无法使用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 :: find和自定义比较,或者循环遍历列表暴力并自己找到它,但似乎应该有更好的方法。
我是否遗漏了一些显而易见的东西,或者这是否过于非标准用于去除干净/正常的方式?
答案 0 :(得分: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
,但无论如何,上述内容都是无害的。
答案 1 :(得分: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的建议重新启用_shared_from_t这是好的;最好避免使用原始tThisPtr。
答案 2 :(得分:3)
enable_shared_from_this
可以帮助解决您的问题,但这需要您在列表中使用的类型来自它:
如果类型启用了该功能,您可以通过调用shared_from_this()
从对象本身获取共享指针。
答案 3 :(得分:0)
您可以使用共享指针将其删除吗?
std::list< boost::shared_ptr<T> > myList;
boost::shared_ptr<T> tThisPtr = new T();
{
myList.push_back(tThisPtr);
}
{
myList.remove(tThisPtr);
}