STL-map的operator[]到底是怎么回事

来看一道题:请统计数组strs里各个字符出现的次数。(使用map)
string strs[] = { “sort”, “sort”, “second”, “sort”, “first”, “first” };
那么最直观,最容易想到的方法,就是用first来存字符,second来存次数。


    map<string, size_t> countMap;//first为string类型存字符,second为size_t类型存次数
    for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); i++)
    {
        map<string, size_t>::iterator it = countMap.find(strs[i]);
        //map的find:如果找到,返回该节点的迭代器,如果没有找到,返回end
        if (it != countMap.end())//之前已经存在,那么second++
        {
            it->second++;
        }
        else//之前没有,则插入
        {
            countMap.insert(make_pair(strs[i], 1));//make_pair是模板函数,自动推演类型,不用多写类型
        }
    }

这样简单易懂的方法,不需多说,那么接下来,看一下map的insert到底是怎么实现的呢?

pair<iterator,bool> insert (const value_type& val);

可以看到,返回值为pair,first是迭代器,second为bool值。
阅读文档,可知:
如果插入之前没有的值,那么iterator指向插入之后的该节点,true
如果插入之前已经有的值,那么iterator指向本来存在的该节点,false

例如:

    map<string, size_t> countMap;
    pair<map<string, size_t>::iterator, bool> ret = countMap.insert(make_pair("sort", 1))

因为countMap里之前没有”sort”,所以顺利插入,ret的first指向该节点,second为true。
这里写图片描述
继续插入:

    pair<map<string, size_t>::iterator, bool> ret2 = countMap.insert(make_pair("sort", 2));

此时”sort”已经存在,所以ret的first指向之前的节点,second为false。
这里写图片描述

现在已经了解了insert的用法,那么刚才的第一中方法就有一些不好,因为insert一定是查找了,find也是查找了,所以效率不够高。

基于对insert的理解,我得出了第二种方法:

    for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); i++)
    {
                pair<map<string, size_t>::iterator, bool> ret = countMap.insert(make_pair(strs[i], 1));

        if (ret.second == false)
        {
            ret.first->second++;//ret.first是指向该节点的迭代器,ret.first->second表示该节点出现的次数
        }
    }

ret是pair类型,插入之后:first为指向strs[i]的迭代器,second为是否成功
如果str[i]不存在,iterator指向插入之后的节点,bool为true,iterator指向的second为1
如果str[i]存在,iterator指向本来存在的节点,但是本来存在的second并没有++,所以需要手动++

这个方法确实不错,接下来介绍重头戏,operator[]

        mapped_type& operator[](const key_type& k)
        {
            return (*((this->insert(make_pair(k, mapped_type()))).first)).second;
        }

mapped_type是V类型,所以mapped_type()就是调用V类型的默认构造函数; key_type是K类型。‘
仔细看这段代码:
他的意思是插入first为传入的k,second为该类型的默认值之后返回的pair,它的first指向k的节点的迭代器,second为true或是flase,接着取first的解引用,那么它的first实际上就是k,second就是V类型的默认值。
那么知道了这点,看看这样插入怎么样:

dict["sort"] = "排序"

insert的返回值里first指向构造的节点,该节点的first为”sort”,second为string默认值,然后将second赋值为”排序”。

那么这道题就有了第三种解法:

    for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]); i++)
    {
        ++countMap[strs[i]];
    }

首先这是正确的:

这里写图片描述
首先operator[],插入了strs[i],成功或者失败,然后得到了该节点的second,出现一次就++一次,那么就可以统计出来次数。

这就是map的operator[]的用法。

猜你喜欢

转载自blog.csdn.net/han8040laixin/article/details/80068044
今日推荐