假设您拥有一个
std::unordered_set<std::shared_ptr<A>> as;
// (there is an std::hash<std::shared_ptr<A>> specialisation)
如果你想在迭代时替换其中的一些元素:
for (auto it = as.begin(); it != as.end(); ++it) {
if ((*it)->condition()) {
as.erase(it);
as.insert(std::make_shared<A>(**it));
}
}
这可能会使erase
和insert
中的迭代器无效(如果重新散列),因此该循环将展示未定义的行为,并且很可能会崩溃。
我能想到的一个解决方案是使用两个独立的vector
来缓冲insert
和erase
操作,然后使用接受迭代器对的重载进行删除和插入(这可能更加友好地执行重新散列)。
即使我使用了缓冲区方法,这仍然似乎是臃肿的代码,并且可能会导致两次重新散列,这两次重新散列都可能是不必要的。
所以,有更好的方法吗?
assign
方法,它可以有效地将容器重置为一个新内容。 - Matthieu M.operator=
,有什么优势? - bitmaskvector
或list
,有一个,但似乎关联容器没有一个。通常的优点是您不需要构造临时存储(就像在这里所做的那样)。您始终可以通过使用as.clear(); as.insert(buffer.begin(), buffer.end());
来模拟它,尽管在列表等中分配(assign)可能通过重用现有存储而不是逐个释放和重新分配节点来进行更好的优化。 - Matthieu M.operator=
很可能是常数时间,因为它会将内容从临时对象中交换出来。但我从来不确定何时必须使用std::move
来允许这种行为。 - bitmaskvector
(因为它很简单)。如果你取一个有5个元素的向量,并使用3个元素应用assign
,它只会覆盖前3个元素并设置大小。如果你首先构建一个新的向量(使用operator=
),那么你将需要为这个新向量动态分配内存。 - Matthieu M.