我有一个unordered_map,它将int作为键存储为值。我需要检查密钥的存在。如果密钥不可用,我需要插入密钥和值。哪一个是更好的方法?
感谢。
unordered_map<int, classA*>testMap;
classA* ptr = testMap[1];
if(ptr == NULL)
testMap[1] = new classA;
OR
unordered_map<int, classA*>::iterator it = testMap.find(1);
if(it == testMap.end())
{
testMap.insert(make_pair(1, new classA));
}
答案 0 :(得分:6)
这两种方法都不是很好,因为它们都会在地图中使用两个查询,而这些查询就足够了。
更好的方法是检索对元素的引用,如果该引用是空指针,则赋值给它:
classA*& ptr = testMap[1];
if (ptr == 0)
ptr = new classA;
这是有效的,因为在地图中查询不存在的元素会自动插入它(默认构造,因此会插入空指针),operator[]
会返回引用元素(无论是新创建的还是已存在的)。
但请注意,此方法(或您的第一个方法)与第二个方法之间的语义略有不同:如果映射中不存在键,则第二种方法仅插入元素。如果密钥实际上已经存在,我的方法(和你的第一个方法)也会创建一个新元素,但它的值是一个空指针。
答案 1 :(得分:1)
第二种是更好的方法。首先,当您执行classA* ptr = testMap[1]
时,您将使用默认值NULL
在哈希中创建项目。
如果您要将地图值更改为指针以外的其他值(例如,可能是vector
),那么您可能没有合适的默认值来进行测试。此外,将来NULL
可能是地图的有效值,因此您的默认值测试将毫无意义。
答案 2 :(得分:0)
我会做以下事情:
typedef unordered_map<int, classA*>::iterator my_iterator;
std::pair<my_iterator, my_iterator> range = testMap.equal_range(1);
if (range.first == range.second) //element not in map
{
testMap.insert(range.first, new classA);
}
编辑:感谢李杰指出这是毫无意义的。如果找不到equal_range
的值,[end, end]
会返回underoded_map
对。
答案 3 :(得分:0)
在效率方面,我认为它们是等效的。
在第一种情况下,如果条目尚不存在,则调用:
classA* ptr = testMap[1];
实际上会在地图中创建一个空元素,然后在if语句中填充。
第二个只会在您拨打insert
时向地图添加一个条目。
所以我认为归结为哪种风格更适合你!