• map中的erase成员函数用法


    转载于 http://www.cnblogs.com/graphics/archive/2010/07/05/1771110.html

        http://hi.baidu.com/sdkinger/item/dcad78e374707ff12b09a453

    一、

    #include <iostream>
    #include <map>
    #include <string>
    using namespace std ;
    
    int main(void) 
    { 
        map<int, string> m ;
        m.insert(pair<int, string>(1, "abc")) ;
        m.insert(pair<int, string>(2, "def")) ;
        m.insert(pair<int, string>(3, "def")) ;
        m.insert(pair<int, string>(4, "ghi")) ;
    
    
        map<int, string>::iterator itor ;
    
        // 错误的写法
        for (itor = m.begin(); itor != m.end(); ++itor)
        {
            if (itor->second == "def")
            {
                m.erase(itor) ; // map是关联式容器,调用erase后,当前迭代器已经失效
            }
        }
    
        // 正确的写法
        for (itor = m.begin(); itor != m.end();)
        {
            if (itor->second == "def")
            {
                m.erase(itor++) ; // erase之后,令当前迭代器指向其后继。
            }
            else
            {
                ++itor;
            }
        }
    
        // 另一个正确的写法,利用erase的返回值,注意,有些版本的stl-map没有返回值,比如SGI版,但vc版的有
        for (itor = m.begin(); itor != m.end();)
        {
            if (itor->second == "def")
            {
                itor = m.erase(itor) ; // erase的返回值是指向被删除元素的后继元素的迭代器
            }
            else
            {
                ++itor;
            }
        }
    
        // Print m
        map<int, string>::const_iterator citor ;
        for (citor = m.begin(); citor != m.end(); ++citor)
        {
            cout << citor->first << ":" << citor->second << endl ;
        }
    
        getchar() ; 
        return 0 ; 
    } 

     二、

    STL的map表里有一个erase方法用来从一个map中删除掉指令的节点
    eg:
    map<string,string> mapTest;
    typedef map<string,string>::iterator ITER;

    ITER iter=mapTest.find(key);
    mapTest.erase(iter);

    像上面这样只是删除单个节点,map的形为不会出现任务问题,
    但是当在一个循环里用的时候,往往会被误用,那是因为使用者没有正确理解iterator的概念.
    像下面这样的一个例子就是错误的写法,
    eg.
    for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
    {
    cout<<iter->first<<":"<<iter->second<<endl;
    mapTest.erase(iter);
    }

    这是一种错误的写法,会导致程序行为不可知.究其原因是map 是关联容器,对于关联容器来说,如果某一个元素已经被删除,那么其对应的迭代器就失效了,不应该再被使用;否则会导致程序无定义的行为。
    可以用以下方法解决这问题:
    正确的写法
    1.使用删除之前的迭代器定位下一个元素。STL建议的使用方式
    for(ITER iter=mapTest.begin();iter!=mapTest.end();)
    {
    cout<<iter->first<<":"<<iter->second<<endl;
    mapTest.erase(iter++);
    }

    2. erase() 成员函数返回下一个元素的迭代器
    for(ITER iter=mapTest.begin();iter!=mapTest.end();)
    {
    cout<<iter->first<<":"<<iter->second<<endl;
    iter=mapTest.erase(iter);
    }

    注意:

    map的earse应注意:
    map这种容器的下边访问和Vector等容器的下标访问有本质的区别。 
    对于Vector容器,用aVector[i]访问第i个元素时,如果元素不存在,容器不会增加元素, 
    而对于map,用aMap[key] 
    访问键key对应的对象时,如果该键对应的对象存在,则返回该对象(这和Vector一样),但是,当键值为key的元素不存在时,容器会自动的增加一个pair,键为key,而值则为一个容器定义时指定的类型并默认初始化(即,如果该类型为基本类型,则初始化为0,比如本例中,aMap[1]的使用会产生一个pair,<1,NULL>,若该类型为类类型,则调用默认构造函数初始化之) 

    显然,本例中,aMap[1]为NULL,后面的erase()不会执行,使得后面的 
    插入语句aMap.insert(1,new A())键值冲突 

    eg:如下代码会导致错误

    #include <iostream> 
    #include <map> 

    using namespace std; 

    struct A 

    A(int i) 

    x=i; 

    int x; 
    }; 

    int main() 

    map<int,A*> amap; 
    if ( amap[1] != NULL ) 
    amap.erase(1); 
    amap.insert(make_pair(1,new A(1))); 
    amap.insert(make_pair(2,new A(2))); 
    amap.insert(make_pair(3,new A(3))); 
    return 0; 
    }

    清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
  • 相关阅读:
    几个不同的关键XPath概念
    go get 下载的包放在哪里呢?
    之前写的关于chromedp的文章被别人转到CSDN,很受鼓励,再来一篇golang爬虫实例
    微信小程序填坑之旅(2)-wx.showLoading的时候,仍能点击穿透,造成重复点击button的问题
    微信小程序填坑之旅(1)-app.js中用云开发获取openid,在其他页上用app.globaldata.openid获取为空
    JS 定时器-setInterval、clearInterval、setTimeout
    微信小程序开发入门教程(四)---自己动手做个小程序
    MT【247】恒成立画图像
    MT【246】方程根$acksim$图像交点
    MT【245】小概率事件
  • 原文地址:https://www.cnblogs.com/hello-yz/p/3235187.html
Copyright © 2020-2023  润新知