如何在迭代unordered_set时有效地替换元素
How to efficiently replace elements in an unordered_set while iterating over it?
假设你有一个
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
操作,然后使用重载来执行迭代器对进行擦除和插入(这可能更适合重新散列)。
即使我使用缓冲区方法,这仍然看起来很臃肿的代码,并可能导致两次可能都是不必要的重新哈希。
那么,有没有更好的方法呢?
我只是想到了一种可能的方法(就在询问之后),但也许还有更好的方法。
将所有内容复制到向量,然后从向量重建集合应该更快:
std::vector<std::shared_ptr> buffer;
buffer.reserve(as.size());
for (auto it = as.begin(); it != as.end(); ++it) {
if ((*it)->condition()) {
buffer.push_back(std::make_shared<A>(**it));
} else {
buffer.push_back(*it);
}
}
as = std::unordered_set<std::shared_ptr<A>>(buffer.begin(),buffer.end());
当您调用as.erase(it)
迭代器时,迭代器it
失效。插入到无序关联容器中会使所有迭代器失效。因此,插入需要与迭代器分离。为了避免处理新插入的对象,还需要避免插入:
std::vector<std::shared_ptr<A>> replaced;
for (auto it = as.begin(); it != as.end(); ) {
if ((*it)->condition()) {
replaced.push_back(std::make_shared<A>(**it));
as.erase(it++);
}
else {
++it;
}
}
std::copy(replaced.begin(), replaced.end(), std::inserter(as, as.begin());
我会把这个作为对@bitmask答案的评论。为什么不直接将矢量用于替换的元素?
std::vector<decltype(as)::value_type> buffer;
buffer.reserve(as.size());
for (auto it = as.begin(); it != as.end(); )
{
if ((*it)->condition())
{
buffer.push_back(*it);
it = as.erase(it);
}
else
{
++it;
}
}
as.insert(buffer.begin(),buffer.end());
而且,如果*it
已经是shared_ptr<A>
,我看不出再次make_shared()
的理由。只需赋值并让复制构造函数/赋值运算符发挥他们的魔力。
在您的情况下,您可以交换我认为:
for(auto iter = as.begin(); iter != as.end(); ++iter)
{
if(/*Check deletion condition here*/)
{
auto newItem = std::make_shared<A>(/*...*/);
swap(*iter, newItem);
}
}
相关文章:
- 有效地使用std::unordered_map来插入或增加键的值
- 如何有效地在 std::vector 中插入一对?
- 有效地计算多维数组的累积和?
- 如何有效地计算将单位立方体映射到自身的反射和旋转?
- 有效地将大数存储为 2 的幂用于路径问题
- 如何在C++中写入 1000 个文件时有效地缓冲
- 如何有效地找到数组中三元组和的最小差异?
- 如何在C++中有效地将数字值重新分配给字符数组
- C++有效地找到向量中第一个最接近的匹配值?
- 如何有效地操作满足给定谓词的向量中的所有项目?
- 有效地将数据加载到 std::vector 中<char>
- 如何在使用 cin 请求 int 时有效地使用户输入万无一失?
- C++:有效地将Sha256摘要放入OpenSSL Bignum?
- 如何有效地收集给定数组中的重复元素?
- 如何有效地修剪和合并四叉树中的节点?
- 可以有效地转换 std::any 与 std::any_cast
- 如何有效地用不同的整数元素替换字符字符串的元素
- 如何在迭代unordered_set时有效地替换元素
- 如何有效地替换C++中的德语变音符号
- 如何在不重新建立堆不变量的情况下有效地替换堆的顶部元素