【问题标题】:How can I use std::remove on a container with std::tr1::weak_ptr?如何在带有 std::tr1::weak_ptr 的容器上使用 std::remove?
【发布时间】:2009-09-07 17:37:30
【问题描述】:

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

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

【问题讨论】:

  • 如果弱指针因为它指向的东西已经消失而不能被锁定会发生什么?
  • 使用 sbk 的回答,p.lock() 会返回一个 shared_ptr 给 p,它不会匹配 theItem.lock(),所以它仍然可以工作。 p.lock() 从不抛出。

标签: c++ stl tr1


【解决方案1】:

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

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() 调用并且非常关心性能,那么最好避免它。

【讨论】:

    【解决方案2】:

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

    创建一个函数来比较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));
        }
    

    不要忘记包含&lt;tr1/functional&gt;

    【讨论】:

    • 看来您应该改用函数对象,并通过引用获取参数。
    【解决方案3】:

    我认为 sbk 方法的问题是weak_ptr 运算符== 具有竞争的潜力。即使从 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
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 2014-12-17
      • 1970-01-01
      • 2016-08-03
      • 2012-11-21
      相关资源
      最近更新 更多