简介
map是<键—值>对的集合 如:map< string ,int> word_count。map类型通常可理解为关联数组:可使用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。
要使用map对象,则必须包含map 头文件。 #include < map >. 在定义map 对象时,必须分别指明键和值的类型:
记住!!!在vector < string,list< int > > 这种容器里边的类型也是容器的时候 >之间是有空格的,不然就变成>>运算符了
对于键类型,唯一得约束就是必须支持 < 操作符,其他不作要求。所以,不能拿(list 类型的迭代器)做键类型,因为(9.2节)list 的迭代器不支持算术运算,也不支持关系运算。它只支持前置和后置的自增、自减运算以及相等(不相等)运算。
value_type该类型比前面介绍的容器所使用的元素类型要复杂得多,value_type 是存储元素的键以及值的pair类型,而且键为const。所以键初始化之后是不能再被赋值的
在学习map的接口时,需要谨记value_type 是pair类型的,它的值成员可以修改,但键成员不能修改!!!!。
- 使用下标访问map与使用下标访问数组或vector的行为截然不同:用下标访问不存在的元素将导致在map容器中添加一个新的元素,它的键即为该下标值。
有别于vector或string类型,map下标操作符返回的类型与对map迭代器进行解引用获得的类型不相同。
- 显然,map迭代器返回value_type类型(pair类型)的值—–包括const key_type 和mapped_type类型成员的pair对象;下标操作符返回的是存储在map里面的值,是一个mapped_type类型的值。
map类额外定义了两种类型:key_type、mapped_type,以获得键或值的类
=================================================================================================
一、map对象的定义
- map是<键—值>对的集合 。map类型通常可理解为关联数组:可使用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。
1、map 对象的定义———-是一个<键—值>对的集合
- 要使用map对象,则必须包含map 头文件。 #include
map<string,int> word_count;//空的map对象,由string类型的键索引,关联的值则为int类型。
2、键类型的约束————必须能够进行 < 操作
在使用关联容器时,它的键不但有一个类型,而且还有一个相关的比较函数。默认情况下,标准库使用键类型定义的 < 操作符类实现键的比较。15.8.3 会再介绍
所用的比较函数必须在键类型上定义严格弱排序。所谓的严格弱排序可理解为键类型数据上的”小于“关系。
实际应用中,键类型必须定义 < 操作符,而且该操作符应能“正确地工作”
对于键类型,唯一得约束就是必须支持 < 操作符,其他不作要求。
//如果我们已经定义了一个ISBN的类型,这个是为书进行编号的。
map<ISBN,Sale_item> bookstore;
//以ISBN类型的对象为索引,所有元素都存储了一个关联的Sale_item类类型实例。
//习题 10.6
//解答:可以定义map对象以vector<int>::iterator 和pair <int,string>为键关联int型对象。但是不能定义map对象以list<int>::iterator 为键关联int型对象。因为键类型必须支持 < 操作,而list 容器的迭代器类型不支持<操作 (9.2节)。
二、map定义的类型——value_type类型是pair类型的
类似于顺序容器里面定义了size_type 类型(vector< int>: : size_type),map也定义了自己的类型。
上图是顺序容器里面定义的类型,有些同样适用于map。
- map 对象的元素是键–值对,也即每个元素包含两个部分:键以及由键关联的值。map 的value_type 就反映了这个事实。
该类型比前面介绍的容器所使用的元素类型要复杂得多,value_type 是存储元素的键以及值的pair类型,而且键为const类型,所以键初始化之后是不能再被赋值的。如word_count数组的value_type为pair
map<string,int> word_count;//空的map对象,由string类型的键索引,关联的值则为int类型。
1、map迭代器进行解引用将产生pair类型的对象
对迭代器进行解引用时,将获得一个引用,指向容器中一个value_type类型的值。对于map容器,其value_type是pair类型:
对迭代器进行解引用将获得一个pair对象,它的first成员存放键,为const,而second成员存放值。
map<string,int>::iterator map_it=word_count.begin();//定义一个迭代器,指向word_count的第一个元素
cout<<map_it->first;//输出第一个位置上的值--键
cout<<" "<<map_it->second;//输出值
map_it->first = "new key";//错误!!!因为键值是const类型的
++map_it->second;//通过迭代器修改值
2、map容器额外定义的类型别名(typedef)
- map类额外定义了两种类型:key_type、mapped_type,以获得键或值的类型。对于word_count,其key_type是string类型,而mapped_type是int型。如同顺序容器一样(9.3.1),可使用作用域操作符来获取类型成员,如 map
三、给map添加元素
- 定义了map容器后,下一步工作就是在容器中添加键—-值元素对,可以使用insert 成员实现,或者,先用下标操作符获取元素,然后给获取的元素赋值。在这种情况下,一个给定的键只能对应与一个元素。
四、使用下标访问map对象
使用下标访问map与使用下标访问数组或vector的行为截然不同:用下标访问不存在的元素将导致在map容器中添加一个新的元素,它的键即为该下标值。
如同其他下标操作符一样,map的下标也使用索引(键)来获取该键所关联的值。如果键已经在容器中,则map的下标运算与vector的下标运算行为相同:返回该键所关联的值。
只有在所查找的键不存在时,map容器才为该创建一个新的元素,并将它插入到此map对象中。此时,所关联的值采用值初始化:类类型的元素用默认构造函数初始化,而内置类型的元素则初始化为0
map<string , int> word_count;//空的map容器
word_count["Anna"]=1;
上述代码发生了如下的事情:
在word_count 中查找键为Anna 的元素,没有找到
将一个新的键—值对插入到word_count中,它的键是const sring类型的对象,保存Anna。而它的值则采用值初始化,这就意味着在本例中值为 0
将这个新的键—值对插入到word_count中。
读取新插入的元素,并将它的值赋为1.
//习题 10.10
map<int,int> m;//首先创建一个空的map容器m,然后在m中增加一个键为0的元素,并将其赋值为1.
m[0]=1;
vector<int> v;//空的容器。
v[0]=1;//错误!!!vector不能通过下标进行初始化!!只能通过push_back,insert 等幻术增加元素。
1、下标操作符返回值的使用
通常来说,下标操作符返回左值。它返回的左值是特定键所关联的值。
有别于vector或string类型,map下标操作符返回的类型与对map迭代器进行解引用获得的类型不相同。
显然,map迭代器返回value_type类型的值—–包括const key_type 和mapped_type类型成员的pair对象;下标操作符返回一个mapped_type类型的值。
cout<<word_count["Anna"];//返回1
++word_count["Anna"];
cout<<word_count["Anna"];//返回2
2、下标行为的编程意义
- 对于map容器,如果下标所表示的键在容器中不存在,咋添加新元素,这一特性可使程序员简练:
map<string,int> word_count;
string word;
while(cin>>word)
++word_count[word];
//这段程序用来记录每个单词出现的次数。while循环每次从标准输入中读入一个单词,如果这是新的单词,则在word_count中添加以该单词为索引的新元素。同时将它的值初始化为0、然后其值立即加1,所以每次在map中添加新元素时,所统计的出现次数正好从1开始。
//习题 10.9
#include <iostream>
#include<vector>
#include<string>
#include<map>
using namespace std;
int main()
{
map<string,int> map_count;
string word;
while(cin>>word)
++map_count[word];
for(map<string,int>::iterator iter=map_count.begin();iter!=map_count.end();++iter)
{
cout<<(*iter).first<<endl;//通过点运算符
cout<<iter->second<<endl;//结果和(*iter).second一样
}
return 0;
}