28

我大致有以下代码。这可以做得更好或更有效吗?也许使用std::remove_if?您可以在遍历地图时从地图中删除项目吗?我们可以避免使用临时地图吗?

typedef std::map<Action, What> Actions;
static Actions _actions;

bool expired(const Actions::value_type &action)
{
  return <something>;
}

void bar(const Actions::value_type &action)
{
  // do some stuff
}

void foo()
{
  // loop the actions finding expired items
  Actions actions;
  BOOST_FOREACH(Actions::value_type &action, _actions)
  {
    if (expired(action))
      bar(action);
    else
      actions[action.first]=action.second;
    }
  }
  actions.swap(_actions);
}
4

4 回答 4

53

Mark Ransom 算法的一种变体,但不需要临时算法。

for(Actions::iterator it = _actions.begin();it != _actions.end();)
{
    if (expired(*it))
    {
        bar(*it);
        _actions.erase(it++);  // Note the post increment here.
                               // This increments 'it' and returns a copy of
                               // the original 'it' to be used by erase()
    }
    else
    {
        ++it;  // Use Pre-Increment here as it is more effecient
               // Because no copy of it is required.
    }
}
于 2008-10-07T23:01:19.020 回答
30

您可以使用erase(),但我不知道BOOST_FOREACH 将如何处理无效的迭代器。map::erase的文档指出只有被擦除的迭代器会失效,其他的应该没问题。以下是我将如何重组内部循环:

Actions::iterator it = _actions.begin();
while (it != _actions.end())
{
  if (expired(*it))
  {
    bar(*it);
    Actions::iterator toerase = it;
    ++it;
    _actions.erase(toerase);
  }
  else
    ++it;
}
于 2008-10-07T21:54:39.233 回答
4

似乎没有人知道的是,当在任何容器上使用时,erase 返回一个新的、保证有效的迭代器。

Actions::iterator it = _actions.begin();
while (it != _actions.end())
{
  if (expired(*it))
  {
    bar(*it);
    it = _actions::erase(it);
  }
  else
    ++it;
}

在这种情况下,存储 actions.end() 可能不是一个好计划,因为我相信迭代器的稳定性不能得到保证。

于 2008-10-07T22:18:54.427 回答
1

如果想法是删除过期项目,为什么不使用map::erase?这样,您只需删除不再需要的元素,无需使用您想要保留的所有元素重建整个副本。

这样做的方法是保存指向要擦除的元素的迭代器,然后在迭代结束后将它们全部擦除。

或者,您可以保存访问过的元素,移动到下一个元素,然后删除临时元素。但是,在您的情况下,循环边界会变得混乱,因此您必须自己微调迭代。

根据 expired() 的实现方式,可能还有其他更好的方法。例如,如果您正在跟踪时间戳作为地图的键(如 expired() 所暗示的那样?),您可以对当前时间戳执行 upper_bound,并且范围 [ begin(), upper_bound() ) 中的所有元素都需要被处理和删除。

于 2008-10-07T21:33:45.000 回答