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

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

map类额外定义了两种类型:key_type和mapped_type,以获得键或值的类型。对于word_count,其key_type是string类型(注意不是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;

有别于vector或string类型。map下标操作符返回的类型与对map迭代器进行解引用或的类型不同:map迭代器返回的是value_type类型的值–
包括constkey_type和mapped_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 << "\tSecond: " << 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:\t\tTimes:" << endl;
for (map<string,int>::iterator iter = word_cnt.begin(); iter != word_cnt.end(); ++iter)
{
cout << iter -> first << "\t\t" << 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)

beg和end是标记元素范围的迭代器,当中的元素必须为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对象。该pair的first成员是一个map迭代器,指向插入的键。

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

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

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

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

C++ Primer 学习笔记_35_STL实践与分析(9)--map种类(在)的更多相关文章

  1. C++ Primer 学习笔记_32_STL实践与分析(6) --再谈string类型(下)

    STL实践与分析 --再谈string类型(下) 四.string类型的查找操作 string类型提供了6种查找函数,每种函数以不同形式的find命名.这些操作所有返回string::size_typ ...

  2. C++ Primer 学习笔记_43_STL实践与分析(17)--再谈迭代器【中】

    STL实践与分析 --再谈迭代器[中] 二.iostream迭代[续] 3.ostream_iterator对象和ostream_iterator对象的使用 能够使用ostream_iterator对 ...

  3. C++ Primer 学习笔记_46_STL实践与分析(20)--容器特有的算法

    STL实践与分析 --容器特有的算法 与其它顺序容器所支持的操作相比,标准库为list容器定义了更精细的操作集合,使它不必仅仅依赖于泛型操作.当中非常大的一个原因就是list容器不是依照内存中的顺序进 ...

  4. C++ Primer 学习笔记_44_STL实践与分析(18)--再谈迭代器【下】

    STL实践与分析 --再谈迭代器[下] 三.反向迭代器[续:习题] //P355 习题11.19 int main() { vector<int> iVec; for (vector< ...

  5. C++ Primer 学习笔记_40_STL实践与分析(14)--概要、先来看看算法【上】

    STL实践与分析 --概述.初窥算法[上]     标准库容器定义的操作很少.并没有给容器加入大量的功能函数.而是选择提供一组算法,这些算法大都不依赖特定的容器类型,是"泛型"的. ...

  6. C++ Primer 学习笔记_45_STL实践与分析(19)--建筑常规算法

    STL实践与分析 --泛型算法的结构 引言: 正如全部的容器都建立在一致的设计模式上一样,算法也具有共同的设计基础. 算法最主要的性质是须要使用的迭代器种类.全部算法都指定了它的每一个迭代器形參可使用 ...

  7. C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器

    STL实践与分析 --容器适配器 引: 除了顺序容器.标准库还提供了三种顺序容器适配器:queue,priority_queue和stack.适配器是标准库中的概念.包含容器适配器,迭代器适配器和函数 ...

  8. C++ Primer 学习笔记_41_STL实践与分析(15)--先来看看算法【下一个】

    STL实践与分析 --初窥算法[下] 一.写容器元素的算法 一些算法写入元素值.在使用这些算法写元素时一定要当心.必须.写入输入序列的元素 写入到输入序列的算法本质上是安全的--仅仅会写入与指定输入范 ...

  9. C++ Primer 学习笔记_38_STL实践与分析(12)--集成的应用程序容器:文本查询程序

    STL实践与分析 --容器的综合应用:文本查询程序 引言: 本章中最重点的实例.由于不须要用到multiset与multimap的内容.于是将这一小节提到了前面.通过这个实例程序,大师分析问题的智慧, ...

随机推荐

  1. poj3667(线段树)

    题目连接:http://poj.org/problem?id=3667 题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 2 a b:将[a,a+b-1]的房间清空 线段树操作:upd ...

  2. 【 D3.js 高级系列 — 8.0 】 打标

    有时,需要在地图上画线.代表"从地方到什么地方"的含义,因此,在连接的映象绘制时.称为"打标". 1. 标线是什么 标线.是指地图上须要两个坐标以上才干表示的元 ...

  3. mysql 开放的telnet

    两步开幕mysql远程连接 一个,登录mysql # mysql -uroot -p 两,配置远程连接 mysql > GRANT ALL PRIVILEGES ON *.* TO 'user1 ...

  4. SICP 1.20经验

    1.20 两者之间的主要区别是,使我们明白的操作顺序. 网上找一些答案,都死了扩大. 我们所从事的IT的. 展开搞死人IT实践. 首先考虑应用程序 我们得到 gcd(206, 40) -> gc ...

  5. 使用Socket沟通

    当两台电脑TCP/IP协议进行通讯.平时Socket对象来表示该通信接口的两端,并通过Socket生产I/O流进行网络通信. 其中ServerSocket对象可以接收从连接的其他通信实体的请求.这个目 ...

  6. bc38 1002, bc39 1002

    比赛的时候是对于每个数,记录下来a[i], 并记录该树的下标hash[a[i]] 然后枚举a[i]的倍数,如果a[i]的倍数存在(设为k*a[i]),那么vis[k*a[i]]是不为0的 那么可以这样 ...

  7. Windows Phone开发(16):样式和控件模板

    原文:Windows Phone开发(16):样式和控件模板 在前面资源一文中也提过样式,样式就如同我们做HTML页排版时常用到的CSS样式表,它是对于特定娄型的可视化元素,应该可以直接说是针对控件的 ...

  8. Python学习路径8——Python对象2

    1.标准型运营商 1.1对象值对照 比较运算符用于如果相同类型的对象是相等.所有的内建类型的是在比较操作中支持,返回布尔比较操作值True 或 False. <span style=" ...

  9. Android:刚6瓶啤酒4两56度白酒下肚,竟然20分钟做了一手机版站点 !

    刚6瓶啤酒4两56度白酒下肚,竟然20分钟不到时间做了一手机版站点 !人有多大潜力你知道吗? 大家有兴趣的能够用手机或微信打开 http://xh.yunxunmi.com/  看看俺这酒后之做! 很 ...

  10. Asp.net网站的简单发布

    概述 网站是由一个个页面组成的,是万维网具体的变现形式,关于万维网,网页的方面的理论知识,大家可以看一看这篇博客:万维网文档,在这里就不多说了.网站的发布要到达的一个目的就是,别人可以通过浏览器访问该 ...