C++ std::map::erase用法及其陷阱

1.引入:

  STL的map中有一个erase方法用来从一个map中删除制定的节点

  eg:

map<string,string> mapTest;
typedef map<string,string>::iterator ITER;
ITER iter=mapTest.find(key);
mapTest.erase(iter);

   像上面这种删除单个节点,map的行为不会出现问题,但是当在一个循环里用的时候,往往会被误用。

2.陷阱

  eg:

for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter);
}  

  这是一种错误的写法,会导致程序行为不可知,原因是map是关联容器,对于关联容器来说,如果一个元素已经被删除,那么其对应的迭代器就失效了,不应该再被使用,负责会导致程序无定义的行为。

3.正确用法

  正确用法一:(C++11可以,C++98不行)

    erase() 成员函数返回下一个元素的迭代器

std::map<std::string, std::string >::iterator it = mapTest.begin();
while(it != mapTest.end())
{
         if(TestVal(it->second))
         {
                 it = mapTest.erase(it);
         }
         else
                 it++;
}  

  正确用法二:

  使用删除之前的迭代器定位下一个元素。STL建议的使用方式

for(ITER iter=mapTest.begin();iter!=mapTest.end();) //注意此处不能再写iter++
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter++);
}  
 在这种用法中,该方法中利用了后++的特点,这个时候执行mapTest.erase(it++);这条语句分为三个过程

      1、先把it的值赋值给一个临时变量做为传递给erase的参数变量

      2、因为参数处理优先于函数调用,所以接下来执行了it++操作,也就是it现在已经指向了下一个地址。

      3、再调用erase函数,释放掉第一步中保存的要删除的it的值的临时变量所指的位置。

4.例子 

  case1: ?

#include<map>
#include<iostream>
int main()
{
        std::map<int, int> map_a;
        std::map<int, int>::iterator it;

        for (int i = 0; i != 10; i++) {
                    map_a.insert(std::map<int, int>::value_type(i, i));
        }

        for (it = map_a.begin(); it != map_a.end(); it++){
                    std::cout<< it->first <<std::endl;
        //              map_a.erase(it->first);
        }

        return 0;
}

结果:

0
1
2
3
4
5
6
7
8
9

  case2:?

#include<map>
#include<iostream>
int main()
{
        std::map<int, int> map_a;
        std::map<int, int>::iterator it;

        for (int i = 0; i != 10; i++) {
                    map_a.insert(std::map<int, int>::value_type(i, i));
        }

        for (it = map_a.begin(); it != map_a.end(); it++){
                    std::cout<< it->first <<std::endl;
                        map_a.erase(it->first);
        }

        return 0;
}

结果:

0
3

当将map大小加到1000000的时候,出core

5.导致程序行为不可知的原因

  5.1 list和vector的erase方法都返回一个iterator,指向被删除元素的下一个元素,唯独map,set,multimap,multiset这4个竟然返回void.

不过在C++11中已经改正过来了,都返回一个iterator

  

原因:迭代器++的操作是在操作它保存的节点指针,所以当这个节点被删除的时候,改节点所指向的指针是无法确定的,也就是可能还是以前的数据,也可能是已经其他毫不相关的数据了,这样的行为被叫做未定义的行为,不一定会core.

时间: 2024-09-28 18:39:21

C++ std::map::erase用法及其陷阱的相关文章

std::map用法

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道.这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树AVL),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处. 使用map对象首先要包括头文件,包含语句中必须加入如下包含声明: #include

C++.stl map::erase陷阱

map::erase函数在不同版本stl中的差异 1. C++98和C++11标准 http://www.cplusplus.com/reference/map/map/erase/ 2. pj stl(windows) map::erase函数的windows实现版本(C++11标准)会返回一个map::iterator: iterator map::erase(const_iterator _Where); iterator map::erase(const_iterator _First,

[转] C++ STL中map.erase(it++)用法原理解析

总结一下map::erase的正确用法. 首先看一下在循环中使用vector::erase时我习惯的用法: for(vector<int>::iterator it = vecInt.begin(); it != vecInt.end();) { if(*it == 0) { it = vecInt.erase(it); } else { it++; } } 程序从一个vector中删除值为0的元素,利用了vector::erase函数根据iterator删除某个元素时会返回下一个元素的ite

C语言 &#183; C++中map的用法详解

转载自:http://blog.csdn.net/sunquana/article/details/12576729 一.定义   (1) map<string,   int>   Map;     (2) 或者是:typedef   map<string,int>   Mymap;                       Mymap   Map; 二.插入数据  插入数据之前先说一下pair 和 make_pair 的用法pair是一个结构体,有first和second 两个

STL中map的用法

map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道.这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处. 下面举例说明什么是一对一的数据映射.比如一个班级中,每个学生的学号跟他的姓名就存在着一一

set/multiset和map/multimap用法小结

二叉搜索树是ACM中经常需要用到的数据结构,熟练掌握map和set的用法很关键,现对其做一个简单的总结. 主要的功能有:插入元素,查找元素,删除,遍历/反向遍历. 现以map为例说明用法,multimap是可以插入重复键值的元素的map. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmat

STL 之 map的用法

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道.这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处. 下面举例说明什么是一对一的数据映射.比如一个班级中,每个学生的学号跟他的姓名就存在着一一

C++ map 的用法归纳2

[尊重原著: http://blog.csdn.net/zcf1002797280/article/details/7847819] Map是c++的一个标准容器,它提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作!1. map构造函数:map<string , int >mapstring; map<int ,string >mapint;map<sring, char>mapstring; map<

C++11中map的用法

最全的c++map的用法 1. map最基本的构造函数:map<string ,int>mapstring; map<int,string >mapint;map<sring,char>mapstring; map< char ,string>mapchar;map<char,int>mapchar; map<int ,char>mapint: 2. map添加数据: map<int ,string>maplive;1.