zoukankan      html  css  js  c++  java
  • C++ Primer 学习笔记_35_STL实践与分析(9)--map种类(在)

    STL实践与分析

    --map类型(上)



    引:

        map是键-值对的集合。

    map类型通常能够理解为关联数组:能够通过使用键作为下标来获取一个值,正如内置数组类型一样;而关联的本质在于元素的值与某个特定的键相关联,而并不是通过元素在容器中的位置来获取。


    一、map对象的定义

    1、定义map对象时,必须分别指明键和值的类型:

        map<string,int> wordCnt;
    


    map的构造函数

    map<K,V>m;

    创建一个名为m空对象,其键和值的类型分别为KV

    map<K,V>m(m2);

    创建m2的对象副本mmm2的键与值的类型必须全然一致

    map<K,V>m(b,e);

    创建map类型的对象m,存储迭代器be标记的范围内全部元素的副本。

    迭代器元素的类型必须能转换为pair<constK, V>


    2、键类型的约束

        在使用关联容器时,它的键不但有一个类型,并且另一个相关的比較函数。默认情况下,标准库使用键类型定义的<操作符来实现键(keytype)的比較。

        对于键类型,唯一的约束就是必须支持<操作符,至于是否支持其它的关系或相等运算,则不作要求。

    //P310 习题10.5
        typedef list<int> lineNo;
        map<string,lineNo> word_line;
        //等同于
        map<string,list<int> > word_line;
    

    二、map定义的类型

    因为map对象的元素是键-值对,因此map对象的value_type是存储元素的键以及值类型的pair类型。并且键为const

    map类定义的类型

    map<K,V>::key_type

    map容器中。用作索引的键类型

    map<K,V>::mapped_type

    map容器中,键所关联的值类型

    map<K,V>::value_type

    一个pair类型:first元素具有

    constmap<K,V>::key_type类型,而second元素则为map<K,V>::mapped_type类型


    1、对map迭代器进行解引用将产生pair类型的对象

        map<string,int> word_count;
        word_count.insert(make_pair("C++ Primer",1));
        map<string,int>::iterator map_iter = word_count.begin();
        cout << map_iter -> first << " "
             << map_iter -> second << endl;
        map_iter -> first = "Effective C++";    //Error
        map_iter -> second = 3;                 //OK
    

    2map容器额外定义的类型别名

        map类额外定义了两种类型:key_typemapped_type,以获得键或值的类型。对于word_count,key_typestring类型(注意不是conststring,mapped_type则是int型。

        map<string,int> word_count;
        word_count.insert(make_pair("C++ Primer",1));
        map<string,int>::iterator map_iter = word_count.begin();
    
        map<string,int>::key_type first = map_iter -> first;
        map<string,int>::mapped_type second = map_iter -> second;
    
        first = "Effective C++";
    
        cout << first << " "
             << second << endl;
    

    三、给map加入元素

    加入元素:

        1、能够使用insert成员实现。

        2、或者先通过下标操作符获取元素,然后给获取的元素赋值。


    四、使用下标訪问map对象

        /** 该程序将发生以下几件事
         *1. 在 word_count 中查找键为 Anna 的元素,没有找到。
         *2. 将一个新的键-值对插入到 word_count 中。它的键是 const string 类型的对象,
         *  保存 Anna。而它的值则採用值初始化,这就意味着在本例中值为 0。

    *3. 将这个新的键-值对插入到 word_count 中。

    *4. 读取新插入的元素,并将它的值赋为 1。 */ map<string,int> word_count; word_count["Anna"] = 1; cout << word_count["Anna"] << endl; cout << word_count["anna"] << endl; cout << word_count.size() << endl;

    使用下标訪问map与使用下标訪问数组或vector的行为截然不同:用下标訪问不存在的元素将导致在map容器中加入一个新元素,它的键即为该下标值

    1、下表操作符返回值的使用

        //通常来说,下标操作符返回左值
        cout << word_count["Anna"] << endl;
        ++ word_count["Anna"];
        cout << word_count["Anna"] << endl;
    

    有别于vectorstring类型。map下标操作符返回的类型与对map迭代器进行解引用或的类型不同:map迭代器返回的是value_type类型的值– 包括constkey_typemapped_type类型的pair对象;而下标操作符返回一个mapped_type类型的值。


    2、使用下标行为的意义

        对于map容器,假设下标所表示的键在容器中不存在,则加入新元素,这一特性可使程序惊人地简练:

        map<string,int> word_cnt;
        string str;
    
        while (cin >> str)
        {
            ++ word_cnt[str];
        }
    
        for (map<string,int>::iterator iter = word_cnt.begin(); iter != word_cnt.end(); ++iter)
        {
            cout << "First: " << iter -> first << "	Second: " << iter -> second << endl;
        }
    

    //P312 习题10.9
    int main()
    {
        freopen("input","r",stdin);
        map<string,int> word_cnt;
        string str;
    
        while (cin >> str)
        {
            ++ word_cnt[str];
        }
    
        cout << "Word:		Times:" << endl;
        for (map<string,int>::iterator iter = word_cnt.begin(); iter != word_cnt.end(); ++iter)
        {
            cout << iter -> first << "		" << iter -> second << endl;
        }
    }
    

    五、map::insert的使用

    map容器中。键影响了实參的类型,vector的区别:

        a.插入单个元素的insert版本号使用键-pair类型的參数。类似地,对于參数为一对迭代器的版本号,迭代器必须指向键-pair类型的元素。

        b. map容器的接受单个值的insert版本号的返回类型。

    map容器提供的insert操作

    m.insert(e)

    e是一个用在m上的value_type类型的值。假设键(e.first)不在m,则插入一个值为e.second的新元素;假设该键在m中已存在,则保持m不变。该函数返回一个pair类型对象,包括指向键为e.first的元素的map迭代器,以及一个bool类型的对象,表示是否插入了该元素

    m.insert(b,e)

    begend是标记元素范围的迭代器,当中的元素必须为m.value_type类型的键-值对。对于该范围内的全部元素,假设它的键在m中不存在,则将该键及其关联的值插入到m

    返回void类型

    m.insert(iter,e)

    e是一个用在m上的value_type类型的值。

    假设键(e.first)不在m,则创建新元素,以迭代器iter为起点搜索新元素存储的位置。返回一个迭代器,指向m中具有给定键的元素


    1、以insert取代下标运算

        //创建一个pair对象,将之直接插入到map容器中
        word_cnt.insert(map<string,int>::value_type("Anna",1));

    使用insert成员能够有效的避免下标操作符带来的副作用:不必要的初始化。

    传递给insert的实參相当笨拙,能够使用两种方法简化:

        1)使用make_pair

        word_cnt.insert(make_pair("Anna",1));
    

        2)使用typedef

        typedef map<string,int>::value_type valType;
        word_cnt.insert(valType("Anna",2));
    

    2、检測insert的返回值

        带有一个键-pair形參insert版本号将返回一个值:包括一个迭代器和一个bool值的pair对象,当中迭代器指向map中具有对应键的元素,bool值则表示是否插入了该元素

    假设该键已在容器中,则其关联的值保持不变,返回的bool值为false,假设该键并不存在于容器中,则bool值为trul。在这两种情况下,迭代器都将指向具有给定键的元素。

        //重写前面的字符统计函数
        map<string,int> word_cnt;
        string word;
    
        while (cin >> word)
        {
            pair<map<string,int>::iterator,bool> res = word_cnt.insert(make_pair(word,1));
    
            if (!res.second)
                ++ res.first -> second;
        }
    

    3、语法展开【解释上面的例程】

    pair<map<string,int>::iterator,bool> res = word_cnt.insert(make_pair(word,1));

    对于:

     ++res.first -> second;

    能够理解为:

       ++((res.first) -> second);

    这个表达式一步步地展开解释:

        1)res存储insert函数返回的pair对象。pairfirst成员是一个map迭代器,指向插入的键

        2)res.firstinsert返回的pair对象中获取map迭代器。

        3)res.first-> second对该迭代器进行解引用,获得一个value_type类型的对象。这个对象相同是pair类型的,它的second成员即为我们所加入的元素的值部分。

        4)++res.first -> second为了实现这一值递增运算符。

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    【干货】整理分布式技术框架常用的算法及策略
    模块(类)之间解耦利器:EventPublishSubscribeUtils 事件发布订阅工具类
    SqlDapperEasyUtil:.NET CORE下的Dapper封装操作类
    JAVA并发同步互斥实现方式总结
    Elasticsearch必知必会的干货知识一:ES索引文档的CRUD
    整理在Spring IOC容器初始化后可以处理特定逻辑的多种实现方式
    C#编写了一个基于Lucene.Net的搜索引擎查询通用工具类:SearchEngineUtil
    干货分享:ASP.NET CORE(C#)与Spring Boot MVC(JAVA)异曲同工的编程方式总结
    .NET CORE与Spring Boot编写控制台程序应有的优雅姿势
    分享基于.NET动态编译&Newtonsoft.Json封装实现JSON转换器(JsonConverter)原理及JSON操作技巧
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4845535.html
Copyright © 2011-2022 走看看