为unordered_map赋值的基本问题

时间:2010-11-24 10:23:28

标签: c++

我有一个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));
}

4 个答案:

答案 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时向地图添加一个条目。

所以我认为归结为哪种风格更适合你!