我有一个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()
(因此使迭代器无效)之前)。正确吗?
答案 0 :(得分:2)
文档说
其他引用和迭代器不受影响
因此您的循环按预期运行,erase
按预期运行。
假设您有4个元素,在这种情况下,循环运行4次没有任何问题。
答案 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错误非常常见,很难防止,我宁愿将相对复杂的循环控制代码放在一个地方。