C++ 无序映射赋值的基本问题

C++ 无序映射赋值的基本问题,c++,C++,我有一个无序的_映射,它将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)

我有一个无序的_映射,它将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));
}
unordered_-maptestMap;
classA*ptr=testMap[1];
如果(ptr==NULL)
testMap[1]=新的classA;
或
无序映射::迭代器it=testMap.find(1);
if(it==testMap.end())
{
insert(make_pair(1,新classA));
}

这两种方法都不好,因为它们都在地图中使用两个查询,其中一个就足够了

更好的方法是检索对元素的引用,如果该引用是空指针,则为其分配:

classA*& ptr = testMap[1];
if (ptr == 0)
    ptr = new classA;
这是因为查询映射中不存在的元素会自动插入它(默认构造,因此将插入空指针),并且
操作符[]
返回对该元素的引用(无论是新创建的还是已经存在的)


但是请注意,此方法(或您的第一个方法)和第二个方法之间的语义有细微的不同:您的第二个方法仅在映射中不存在键时插入元素。如果键实际上已经存在,但其值是空指针,那么我的方法(以及您的第一个方法)也会创建一个新元素。

我将执行以下操作:

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);
}
typedef无序映射::迭代器我的迭代器;
std::pair range=testMap.equal_range(1);
if(range.first==range.second)//元素不在映射中
{
insert(range.first,新classA);
}

编辑:感谢李杰指出这是毫无意义的
equal_range
返回值,如果在编码映射下未找到值,则第二种方法是更好的方法。在第一种情况下,当您执行
classA*ptr=testMap[1]
时,您将在哈希中创建一个默认值为
NULL
的项


如果要将映射值更改为指针以外的其他值(例如,可能是
向量
),则可能没有合适的默认值进行测试。另外,将来,
NULL
可能是地图的有效值,因此默认值测试将毫无意义。

就效率而言,我相信它们是等效的

在第一种情况下,如果条目不存在,则调用:

classA* ptr = testMap[1];
将实际在映射中创建一个空元素,然后在if语句中填充该元素

第二个选项仅在您调用
insert
时向地图添加条目


所以我想这取决于哪种款式更适合你

如果该键已经存在,并且
NULL
是该键的有效值,该怎么办?但这通常不是一个好主意。如果您存储的不是指针,那么您可能没有合适的默认值进行测试。此外,效率在这里也不是问题,因为内存分配比查找要花费更长的时间。@Peter:没错。但在这种情况下,这是最好的方法。至于效率不是问题,我不敢苟同。您是对的,内存分配可能会超过查找。但是,不必要地执行冗余操作并不是不必要的。这并不是不必要的,如果NULL成为有效值,或者如果值的类型发生变化,它会使维护变得更容易。如果元素不在
无序映射中
相等范围
返回的两个迭代器都是
end()
。因此我怀疑
insert
提示是否有用。(即,它相当于
testMap.insert(testMap.end(),new classA)
。这在任何情况下都是一个错误;它应该是一对)。是的,你说得对,我想的是一个标准的有序映射,对不起。我不确定你所说的错误是什么意思,UnderOrder_map有一个插入函数,它接受两个参数,一个迭代器和一个值:我没有向下投票,但我想说第二种方法还有另一个原因:您永远不会创建无效的条目。我建议您将动态创建的
classA
实例存储在
std::shared_ptr
std::unordered_map
中。您可以使用
std::make_shared(…ctr params…)
创建实例。这就减轻了您对资源泄漏的担忧。如果您可以确定映射中永远没有有效的空指针,那么第一种方法或避免第二次查找的变体可能会更好。然而,由于你没有说明前提条件,我会选择第二种安全的方法。可以使用count()函数代替find和/或去掉it局部变量来清除代码。