3

如果我有一个 STL 容器,请说出一个指针列表,我可以像下面的示例中那样删除它们。对于weak_ptrs 的容器,这是行不通的,因为它们无法进行比较,因为它们需要先被锁定。我能做些什么?

void MyClass::RemoveItem(std::tr1::weak_ptr<Item> const & pItem)
{
    mylist.remove(pItem);
}
4

3 回答 3

5

一方面,您可以为任何weak_ptr 定义运算符==。我敢肯定这没有实现是有原因的,它可能会在以后咬你。

template <typename T>
bool operator == (const std::tr1::weak_ptr<T>& a, const std::tr1::weak_ptr<T>& b)
{
    return a.lock() == b.lock();
}

...您将能够像往常一样调用 remove() 。我想这有点极端。

如果您坚持使用 remove_if() 方法,您可以使用函数对象摆脱绑定魔法*:

struct EqPredicate
{
    const boost::weak_ptr<Item>& theItem;

    EqPredicate(const boost::weak_ptr<Item>& item) : theItem(item) 
    {
    }

    bool operator () (const boost::weak_ptr<Item>& p) const 
    { 
        return p.lock() == theItem.lock(); 
    }
};

然后像这样使用它:

mylist.remove_if(EqPredicate(pItem));

它看起来像更多的代码,但你可以压缩 EqPredicate 类,它大部分是空的。此外,可以将其制作为模板以将其与包含 Item 以外的类型的列表一起使用。

哦,并且在任何地方都通过引用传递给你weak_ptrs,包括你的比较函数。

*bind 在性能方面不是免费的。如果您期望大量的 Remove() 调用并且非常关心性能,那么避免它可能会很好。

于 2009-09-07T19:14:26.570 回答
0

只是因为我一直在寻找答案。

创建一个函数来比较weak_ptrs,然后绑定一个参数。

    bool weak_ptr_comparsion(Item::wPtr  a, Item::wPtr  b)
    {
        return a.lock() == b.lock();
    }

    void MyClass::RemoveItem(Item::wPtr const & pItem)
    {
        mylist.remove_if(std::tr1::bind(weak_ptr_comparsion, pItem, 
                         std::tr1::placeholders::_1));
    }

不要忘记包括<tr1/functional>

于 2009-09-07T17:39:35.403 回答
0

我认为 sbk 方法的问题是 weak_ptr operator== 有可能发生竞争。即使从 operator== 返回,也不能保证 a 或 b 的 shared_ptr 存在,这很容易误解生成的代码。

有了它,你能做的最好的似乎是:

if(a == b) {
  boost::shared_ptr<Item> a_locked(a.lock());
  boost::shared_ptr<Item> b_locked(b.lock());
  // It is an error to assume a_locked == b_locked here
  // It is an error to assume a.lock() == b.lock() here
  // It is an error to assume a.get() or b.get() here
}

这不是那么有用。现在,如果您正在对容器进行迭代,此时您仍然可以删除迭代器,但在更多情况下,您最终会做出稍微错误的比较。

于 2012-06-28T17:31:30.357 回答