c++错误的地图删除操作和STL中容器的迭代器的底层实现机制

  介绍

这篇文章将为大家详细讲解有关c++错误的地图删除操作和STL中容器的迭代器的底层实现机制,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

1。错误的地图删除操作

假设有个地图容器,用于存储大学班级中各个家乡省份对应的学生数,主要为省份中文全拼,值为学生数。现需要删除人数为0的记录,删除代码如下:

map<字符串,整数比;countMap; (map<字符串,int>:: iterator它=countMap.begin();它!=countMap.end (); + +)   {如果(它→第二==0)   {   countMap.erase(它);   }   }

猛一看,没问题,仔细一看,有巨坑,STL容器的删除和插入操作隐藏的陷阱主要有如下两条。
(1)对于节点式容器(地图、列表、集)元素的删除,插入操作会导致指向该元素的迭代器失效,其他元素迭代器不受影响;
(2)对于顺序式容器(向量,字符串,双端队列)元素的删除,插入操作会导致指向该元素以及后面的元素的迭代器失效。

所以,在删除一个元素的时候,是没有什么问题的。即:

,(map<字符串,int>:: iterator=countMap.begin();它!=countMap.end (); + +)   {如果(它→第二==0)   {   countMap.erase(它);打破;   }   }

但是,当删除多个元素时,程序会出现崩溃。原因是通过迭代器删除指定的元素时,指向那个元素的迭代器将失效,如果再次对失效的迭代器进行+ +操作,则会带来未定义行为,程序崩溃。解决方法有二,还是以上面地图的容器为例,示例删除操作的正确实现:

<强>方法一:当删除特定值的元素时,删除元素前保存当前被删除元素的下一个元素的迭代器。

map<字符串,int祝辞::iterator nextIt=countMap.begin();为(map<字符串,int>:: iterator=countMap.begin ();。)   {如果(nextIt !=countMap.end ())   {   + + nextIt;   其他}   {   打破;   }如果(它→第二==0)   {   countMap.erase(它);   }   它=nextIt;   }

如何更加简洁的实现该方法呢?下面给出该方法的《有效STL》一书的具体实现:

,(map<字符串,int>:: iterator=countMap.begin();它!=countMap.end ();)   {如果(它→第二==0)   {   countMap.erase (+ +);   其他}   {   + +;   }   }

该实现方式利用了后置+ +操作符的特性,在消除操作之前,迭代器已经指向了下一个元素。

再者map.erase()返回指向紧接着被删除元素的下一个元素的迭代器,所以可以实现如下:

,(map<字符串,int>:: iterator=countMap.begin();它!=countMap.end ();)   {如果(它→第二==0)   {   它=countMap.erase(它);   }   其他的   {   + +;   }   }

<>强方法二:当删除满足某些条件的元素,可以使用remove_copy_if,交换方法。先通过函数模板remove_copy_if按照条件拷贝(副本)需要的元素到临时容器中,剩下未被拷贝的元素就相当于被“删除(删除)”了,然后在将两个容器中的元素交换(交换)即可,可以直接调用地图的成员函数交换。参考代码:

 # include & lt; iostream> # include & lt; string> # include & lt; map> # include & lt; algorithm> # include & lt; iterator>使用名称空间性病;map<字符串,int>mapCount;//不拷贝的条件bool notCopy (pair<字符串,int>key_value)
  {返回key_value.second==0;
  }int main ()
  {
  mapCount.insert (make_pair (“tanwan", 0));
  mapCount.insert (make_pair (“anhui" 1));
  mapCount.insert (make_pair (“shanghai", 0));
  mapCount.insert (make_pair (“shandong" 1));int> map<字符串;mapCountTemp;//临时地图容器//之所以要用迭代器适配器插件函数模板是因为通过调用插入()成员函数来插入元素,并由用户指定插入位置
  mapCount.end remove_copy_if (mapCount.begin()()、隔板(mapCountTemp, mapCountTemp.begin ()), notCopy);
  
  mapCount.swap (mapCountTemp);//实现两个容器的交换
  
  cout<& lt; mapCount.size () & lt; & lt; endl;//输出2
  cout<& lt; mapCountTemp.size () & lt; & lt; endl;//输出4
  
  (map<字符串,int>:: iterator它=mapCount.begin();它!=mapCount.end (); + +)
  {cout<& lt;它→first<& lt;““& lt; & lt;它→second<& lt; endl;
  }
  }

程序输出结果:

2   4   安徽1   山东1

这种方法的缺点:虽然实现两个地图的交换的时间复杂度是常量级,一般情况下,拷贝带来的时间开销会大于删除指定元素的时间开销,并且临时地图容器也增加了空间的开销。

c++错误的地图删除操作和STL中容器的迭代器的底层实现机制