iterator erase(
const_iterator Where);
iterator erase(
const_iterator First,
const_iterator Last);
size_type erase(
const key_type& Key);
由于map只支持erase(const_iterator)或erase(const key_type &Key),即只能使用迭代器或键来删除pair元素。当遍历删除map中的某个元素后,指向那个元素的迭代器将因元素已删除而失效(地址不变,但没意义了,++或--都是没意义的),所以要想在erase掉某迭代器后还要使用该迭代器,必须在erase之前存储其++或--移位后(相对于map“容器”建立时的先后顺序)的迭代器,map是用哈希存储并寻址的,VScode监视map时展示出的“排列顺序”其实只是“map容器”加入元素的先后顺序,并不是地址顺序。删除掉一个中间元素后不会有vector连续容器那样的“移位”、“回填”的后台操作,map删除元素只是释放那个元素建立Hash映射时的堆内存,删除后再定义的迭代器再也不会指向那个元素,而删除前指向那个元素的迭代器的地址虽然不变但已经没意义了。
举个例子:原始map容器各元素地址:
首先再次编译以下:
这里可以很直观地观察到map容器是采用哈希存储的,map元素的地址不连续,并且再次编译后各元素地址的低4个16进制位(对应低位2个字节,测试程序是32位程序,共4字节内存地址可用)保持不变,这其实就是用哈希计算出的pair元素地址。
map是基于红黑树实现。红黑树作为一种自平衡二叉树,保障了良好的最坏情况运行时间,即它可以做到在O(log n)时间内完成查找,插入和删除,在对单次时间敏感的场景下比较建议使用map做为容器。比如实时应用,可以保证最坏情况的运行时间也在预期之内。
unordered_map是基于hash_table实现,一般是由一个大vector,vector元素节点可挂接链表来解决冲突来实现。hash_table最大的优点,就是把数据的存储和查找消耗的时间大大降低,几乎可以看成是常数时间;而代价仅仅是消耗比较多的内存。然而在当前可利用内存越来越多的情况下,用空间换时间的做法是值得的。
删除第一个元素后,原来指向第一个元素的迭代器失效,虽然地址不变,但已经没意义了。而删之前++指向后面元素的迭代器保持自己的指向,要和vector顺序容器的“批量移位”、“批量回填”区别开!。