确定STL映射是否包含给定键的值的最佳方法是什么?
#include <map>
using namespace std;
struct Bar
{
int i;
};
int main()
{
map<int, Bar> m;
Bar b = {0};
Bar b1 = {1};
m[0] = b;
m[1] = b1;
//Bar b2 = m[2];
map<int, Bar>::iterator iter = m.find(2);
Bar b3 = iter->second;
}
在调试器中检查它,iter看起来只是垃圾数据。
如果我取消注释这一行:
Bar b2 = m[2]
调试器显示b2是{i = 0}。(我猜这意味着使用一个未定义的索引将返回一个结构与所有空/未初始化的值?)
这两种方法都不是很好。我真正想要的是这样一个界面:
bool getValue(int key, Bar& out)
{
if (map contains value for key)
{
out = map[key];
return true;
}
return false;
}
是否存在类似的情况?
简单总结一下其他的一些答案:
如果你还没有使用c++ 20,你可以编写自己的mapContainsKey函数:
bool mapContainsKey(std::map<int, int>& map, int key)
{
if (map.find(key) == map.end()) return false;
return true;
}
如果你想避免map和unordered_map以及不同键和值类型的很多重载,你可以把它做成一个模板函数。
如果你使用c++ 20或更高版本,会有一个内置的contains函数:
std::map<int, int> myMap;
// do stuff with myMap here
int key = 123;
if (myMap.contains(key))
{
// stuff here
}
是否存在类似的情况?
不。对于stl map类,您使用::find()来搜索映射,并将返回的迭代器与std::map::end()进行比较
so
map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
//element found;
b3 = it->second;
}
显然,如果你愿意,你可以编写自己的getValue()例程(在c++中也是如此,没有理由使用out),但我怀疑,一旦你掌握了使用std::map::find()的诀窍,你就不会想浪费时间了。
你的代码也有点错误:
m.find (' 2 ');将在映射中搜索键值为'2'的键值。IIRC, c++编译器将隐式地将'2'转换为int型,这将导致'2'的ASCII代码的数值不是你想要的。
因为你在这个例子中的键类型是int,你想这样搜索:
它已经在find only中存在,但语法不完全相同。
if (m.find(2) == m.end() )
{
// key 2 doesn't exist
}
如果你想在值存在的情况下访问它,你可以这样做:
map<int, Bar>::iterator iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
使用c++ 0x和auto,语法更简单:
auto iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
我建议你习惯它,而不是试图想出一个新的机制来简化它。您可能能够减少一些代码,但要考虑这样做的成本。现在您已经引入了一个熟悉c++的人无法识别的新函数。
如果不管这些警告,你还是想实现这个,那么:
template <class Key, class Value, class Comparator, class Alloc>
bool getValue(const std::map<Key, Value, Comparator, Alloc>& my_map, int key, Value& out)
{
typename std::map<Key, Value, Comparator, Alloc>::const_iterator it = my_map.find(key);
if (it != my_map.end() )
{
out = it->second;
return true;
}
return false;
}