基于范围的循环中删除unordered_map元素的简洁合规实现方法
基于范围的std::unordered_map多元素删除方法
你原来的代码问题在于:用std::views::filter生成的视图依赖原容器的迭代器,遍历视图时直接调用erase会导致原容器迭代器失效,破坏视图的遍历逻辑;同时代码里erase(val)是误用——应该传入键而非值(虽然这里碰巧没触发更严重的逻辑错误,但写法本身不符合预期)。
如果想用简洁的基于范围的写法,首选C++20引入的std::erase_if,这是专门为批量删除容器元素设计的算法,内部已经处理好了迭代器失效问题,写法非常清爽:
#include <unordered_map> #include <iostream> int main() { std::unordered_map<int, int> numbers = {{1,2}, {2,1}, {3,2}, {4,5}}; auto even = [](const auto& entry){return entry.second % 2 == 0;}; std::erase_if(numbers, even); // 直接传入容器和判断谓词 for(auto& [key, val] : numbers) { std::cout << key << " " << val << "\n"; } }
这段代码会正确删除所有值为偶数的元素,输出结果是:
2 1 4 5
如果因为环境限制不能用C++20,也可以先通过视图收集所有要删除的键,再批量删除(避免遍历原容器时修改容器):
#include <unordered_map> #include <ranges> #include <vector> #include <iostream> int main() { std::unordered_map<int, int> numbers = {{1,2}, {2,1}, {3,2}, {4,5}}; auto even = [](const auto& entry){return entry.second % 2 == 0;}; // 先收集符合条件的键 std::vector<int> keys_to_erase; for(const auto& [key, _] : numbers | std::views::filter(even)) { keys_to_erase.push_back(key); } // 批量删除 for(int key : keys_to_erase) { numbers.erase(key); } for(auto& [key, val] : numbers) { std::cout << key << " " << val << "\n"; } }
内容的提问来源于stack exchange,提问作者Stein
相关产品推荐
相关产品推荐

