如何有效地将(一些)项目从一个std::map移动到另一个std::map



我有两个std::map<>对象ab,并且希望基于某个谓词p将(extract+insert(一些元素(节点(从一个映射移动到另一个映射。

for (auto i = a.begin(); i != a.end(); ++i)
if (p(*i))
b.insert(a.extract(i))

这个代码在clang中出错。我认为问题是i的节点从中提取后的增量

通过使用后增量来解决这个问题的正确/唯一方法是什么?,例如:

for (auto i = a.begin(); i != a.end();)
if (p(*i))
b.insert(a.extract(i++))
else
++i;

EDIT:我删除了关于"为什么这在gcc中有效?"的部分,因为我无法在当前设置中重现。我确信它曾经在某个时间点发生过,但在gcc 9.2.1中,我出现了死锁(而不是segfault(。无论哪种方式,在extract()之后递增都不起作用。

我认为问题是从a提取节点后I的增量。

确实如此。Extraction会使所提取元素的迭代器无效,而i就是这样的迭代程序。通过无效迭代器递增或间接的行为是未定义的。

为什么这似乎在gcc中有效,但在clang中无效?

因为程序的行为是未定义的。

用后增量来解决这个问题是正确的/唯一的方法吗?

这是解决此问题的正确方法。这不是一个特别糟糕的方式。如果你不想重复增量,一种方法是使用一个变量:

for (auto i = a.begin(); i != a.end();) {
auto current = i++;
if (p(*current)) {
// moving is probably unnecessary
b.insert(a.extract(std::move(current)));
}
}

最新更新