提问人:Ivan Krivyakov 提问时间:10/3/2023 最后编辑:Ivan Krivyakov 更新时间:10/3/2023 访问量:81
如何防止 unordered_map.find() 被比作错误的结束迭代器?[已结束]
How to prevent unordered_map.find() being compared to a wrong end iterator? [closed]
问:
我们刚刚在代码中发现了一个错误,它是这样的:
class foo {
unordered_map<int,string> m_someMap;
public:
void stuff() {
unordered_map<int, string> someMap;
...
auto it = someMap.find(x);
if (it != m_someMap.end()) { // oops! comparing to the end() of a wrong map!
// found x in the map, use it->second here
}
}
}
这里明显的问题是,检查是否成功需要对地图进行两次命名,如果这两次出现不同步,用户要小心。find()
防止这种情况的最佳做法是什么?换言之,如何检查项目是否存在于地图中,而不必说出地图名称两次?
我希望地图迭代器可以转换为 ,这样我就可以写简单的 ,但它们不是。bool
if (it)...
还有其他想法吗? 模板函数,返回 ?现代标准库的一些魔力?safe_find()
optional<unordered_map<int,string>::iterator>>
答:
1赞
kiner_shah
10/3/2023
#1
您可以创建一个免费的模板功能,以避免任何事故:
template<typename K, typename V>
static bool exists_in_unordered_map(const std::unordered_map<K, V>& m, const K& key)
{
return m.find(key) != m.end();
}
然后随时随地使用它:
if (exists_in_unordered_map(someMap, x))
{
// found x, now do something here
}
0赞
Öö Tiib
10/3/2023
#2
最常见的做法是在测试版本中使用调试选项,如 clang、gcc 或 msvc。_LIBCPP_DEBUG
_GLIBCXX_DEBUG
_ITERATOR_DEBUG_LEVEL
这将导致大量的运行时健全性检查,例如不相关的迭代器不会相互比较。因此,您描述的缺陷(以及许多其他缺陷)将更快地被发现和修复。
编写一些运行时检查或辅助逻辑感觉更糟糕。一旦编程错误被修复,那么检查可能只会浪费最终产品的运行时性能,而C++正是因为这种良好的性能而最常用的。
1赞
alagner
10/3/2023
#3
您只需要检查给定键是否存在,还是也需要对找到的元素进行检查?有很多选择,具体取决于要实现的目标和使用的语言版本。
- 返回指针的自定义模板方法,可选,您可以命名它。这是不言自明的。这里很难给出详尽的答案,可以通过多种方式实现。 我可能会选择这样的 sth:
#include <map>
#include <optional>
#include <functional>
#include <type_traits>
template<typename M, typename K>
auto mapFind(M& map, const K& key)
{
using MappedType =
std::conditional_t<std::is_const_v<M>,
const typename M::mapped_type,
typename M::mapped_type>;
using ReturnType = std::optional<std::reference_wrapper<MappedType>>;
auto found = map.find(key);
if (found == map.end()) {
return ReturnType{std::nullopt};
}
return ReturnType{found->second};
}
https://godbolt.org/z/q1qbxKMs7
map::包含
来自 C++20。返回一个布尔值。mapObject.contains(key);
map::count
pre C++20 方式的第二点。稍微丑一点,但有效。mapObject.count(key) > 0;
地图::at
基于例外,因此经常不喜欢或劝阻,但有效。try { mapObject.at(key); } catch (const std::out_of_range& ex) {//handle ex here}
评论
it
found x
optional