我有两个std::map<>
对象a
和b
,并且希望基于某个谓词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)));
}
}