map 与 unordered_map 的区别

map 是有序容器,内部通常由红黑树实现;unordered_map 是无序容器,内部基于哈希表。

因此 unordered_map 的插入、查找、删除速度通常比 map 快数倍。当对数据顺序没有要求时,应尽量使用 unordered_map

使用时的注意事项

  1. 执行 erase 时,为了保证迭代器的正确性,要么写成 erase(it++);,要么写成 it = erase(it);
  2. 使用 for (const auto &x : mapXX) 遍历时,如果在循环体内执行了删除或插入操作,则结果的正确性将无法保证。
  3. 对于某一个具体的迭代器,在其之后执行删除或插入操作时需要特别留意失效问题。

示例代码

unordered_map<int, string> map2;
	map2.insert(pair<int, string>(1, "ARTJSAJSTJ"));
	map2.insert(pair<int, string>(2, "BHWTJUWRTHJSRTJ"));
	map2.insert(make_pair(3, "CHRHEWHEHJT"));
	map2.insert(make_pair(4, "CHRHEWHEHJt"));

	auto it = map2.begin();
	auto itt1 = map2.find(3);

	map2.erase(it);

	cout << (*itt1).second.c_str()<<endl;
	//unorder_map   itt1不会失效






		map<int, string> map1;
		map1.insert(pair<int, string>(1, "ARTJSAJSTJ"));
		map1.insert(pair<int, string>(2, "BHWTJUWRTHJSRTJ"));
		map1.insert(make_pair(3, "CHRHEWHEHJT"));
		map1.insert(make_pair(4, "CHRHEWHEHJt"));



	 	auto it1 = map1.begin();

		auto itt = map1.find(3);

		map1.erase(it1);
		cout << (*itt).second.c_str();
		//map 也不失效

从上面的测试来看,删除和插入操作似乎都不会导致迭代器失效。但对于这个结论我其实有所怀疑,可能只是测试用例本身的原因。

随后在 http://en.cppreference.com/w/cpp/container/map/erase 相关页面中找到了解答,结论整理如下。

erase(删除)

  1. 对于 unordered_maperase 只会使作为参数的那个迭代器失效,其他迭代器不受影响。

References and iterators to the erased elements are invalidated. Other iterators and references are not invalidated

  1. 对于 map,结论相同。

References and iterators to the erased elements are invalidated. Other references and iterators are not affected.

insert(插入)

  1. 对于 unordered_map,如果插入导致了 rehashing,那么所有迭代器都会失效;否则迭代器不会失效。引用始终不会失效。

rehashing 只会在插入新元素后,元素总数超过 max_load_factor() * bucket_count() 时发生。

If rehashing occurs due to the insertion, all iterators are invalidated. Otherwise iterators are not affected. References are not invalidated. Rehashing occurs only if the new number of elements is higher than max_load_factor()*bucket_count().

  1. 对于 map,任何迭代器和引用都不会失效。

No iterators or references are invalidated.

总结

  • 插入:unordered_map 可能导致迭代器失效,map 不受影响。
  • 删除:仅被删除元素对应的迭代器失效,其他迭代器不受影响。