迭代时std :: multimap :: erase()

时间:2018-09-19 22:51:41

标签: c++ c++11

我有一个import matplotlib.pyplot as plt import numpy as np # example data: argument of complex numbers around 0 N = 100 re,im = np.mgrid[-1:1:100j, -1:1:100j] angle = np.angle(re + 1j*im) cmaps = 'twilight', 'twilight_shifted' fig,axs = plt.subplots(ncols=len(cmaps), figsize=(9.5,5.5)) for cmap,ax in zip(cmaps,axs): cf = ax.pcolormesh(re, im, angle, shading='gouraud', cmap=cmap) ax.set_title(cmap) ax.set_xlabel(r'$\operatorname{Re} z$') ax.set_ylabel(r'$\operatorname{Im} z$') ax.axis('scaled') cb = plt.colorbar(cf, ax=ax, orientation='horizontal') cb.set_label(r'$\operatorname{Arg} z$') fig.tight_layout() ,它将会话ID(std::multimap)映射到该会话中使用的硬件(硬件由int描述,其中包含一些特定于硬件的信息)。

我有一个清理功能,必须对每个硬件进行特定的清理工作。清理完成后,我需要从映射中删除该元素,因为该会话中不再使用硬件。

请注意,我不仅要从会话中删除单个硬件。相反,整个会话都被拆除了,因此我想在地图上搜索会话ID,清理硬件,然后从地图上删除所有这些条目。

以下代码显示了我要解释的内容:

struct

循环合法吗?我知道传递给void MyClass::end_session(const int session_id) { // session_map_ is a member variable of MyClass const auto range = session_map_.equal_range(session_id); for (auto it = range.first; it != range.second; session_map_.erase(it++)) { // do cleanup for the hardware pointed to by it->second } } 的迭代器会失效,但这不会使erase()range.first无效,对吗?另外,range.second是否像我期望的那样工作?也就是说,我假设session_map_.erase(it++)被保存为it的参数,并递增到其新值,然后为旧值调用erase()(因此使迭代器无效)之前)。正确吗?

2 个答案:

答案 0 :(得分:2)

文档说

  

其他引用和迭代器不受影响

因此您的循环按预期运行,erase按预期运行。

假设您有4个元素,在这种情况下,循环运行4次没有任何问题。

https://en.cppreference.com/w/cpp/container/multimap/erase

答案 1 :(得分:1)

您所做的事情绝对安全。

但是,我对业务逻辑中的复杂控制流程一无所知。乍一看太难了,评论有可能变得不同步。

我这样写动词。

template<class C, class It, class F>
void erase_remove_if( C& c, It b, It e, F&& f) {
  auto it = b;
  while (it != e) {
    if (f(*it))
      it = c.erase(it);
    else
      ++it
  }
}
template<class C, class F>
void erase_remove_if( C& c, F&& f) {
  using std::begin; using std::end;
  return erase_remove_if( c, begin(c), end(c), std::forward<F>(f) );
}

现在您的代码如下:

void MyClass::end_session(const int session_id) {
  // session_map_ is a member variable of MyClass
  const auto range = session_map_.equal_range(session_id);

  // remove said elements after doing some processing:
  erase_remove_if( session_map_, range.first, range.second, [&](auto& kv) {
    auto&& [key, elem] = kv;
    // do cleanup for the hardware pointed to by elem
    return true; // erase element
  });
}

基本上,fenceposting错误非常常见,很难防止,我宁愿将相对复杂的循环控制代码放在一个地方。