STL入门教程三:map的使用

时间:2021-02-18 20:46:13

       map是C++标准库的关联容器之一,它是一种通过键值(key-value)对组合而成的容器。由于在容器内部对键值对中的键进行了特别的组织,所以我们可以通过搜索容器中的键,来快速的查询到我们所感兴趣的元素。同时,map中的键还具有唯一性。即map中如果存在待插入的键值,则此次的插入操作会失败。了解了这些基本的概念以后,让我们来结合map的具体使用方法,来加深对map的认识。

      首先让我们来学习一下构造函数和赋值操作:

     

      说明:默认构造函数,使用comp对象中定义的规则来创建一个空的map。

      在这里让我们稍微的岔开一点正题,来看一看comp对象,comp对象是对map的内部影响最大的模板参数。map中通过在comp对象中所定义的规则,按照从小到大的顺序来组织容器中的元素排列。这也是关联容器相对于顺序容器的特点之一,及相对于元素而不是相对于元素的绝对位置组织元素。由于使用自定义的comp对象算是在map中最难的,所以在这里我就不马上为大家举一个例子。等到大家学习了一些关于map的知识过后,我会为大家举一个使用自定义comp的例子。

      下面让我们回到正题,来继续看map中的其它构造函数。 

     

       
      说明:重复序列构造函数。将first(包含)到last(不包含)之间的元素复制到map中。


      

      说明:复制构造函数。将x中的元素复制到map中。

 

     

      说明:赋值运算符。将map中原来的元素全部清空后,然后将x中的元素拷贝到map中。

 

      接下来让我们来看一下map中的插入操作:

     

      说明:插入操作。需要注意的是map的insert操作和一般容器的insert操作有点不一样,它并不一定会将传入的键值对加入到容器中。它首先会查找容器中是否存在待插入的键值,如果不存在这样的键值,则将传入的键值对插入到map中;如果存在的话,则不会将键值对插入到map中。

      insert和operator[]是map提供的仅有两个能将新的元素插入到容器中的操作。可能有的同学会感到奇怪,与顺序容器的vector和list相比,map为什么没有提供push_back和push_front这样的操作呢?其实这是由关联容器的性质决定的,因为在关联容器中,元素的位置并不是由元素插入到容器中的先后顺序决定的,而是由一个特定的元素间的关系决定的。例如我们在构造一个map对象的时候,可以传入模板参数comp来定义这种关系。因此push_back和push_front这两个操作当然对于map就是没有意义的。

      好了让我们回到正题,来看一下第一个版本的insert操作中的参数和返回类型。

      参数:x。插入的键值对。可能细心的同学会对value_type这个类型感到有点奇怪,如果按照这个名字直译的话,不是一个值类型吗?即只包含键所对应的值,而没有包含键的值。不过,事实并不是这样的,value_type类型就是一个键值对类型。类型的定义如下:

      

       类型pair是STL中用来表示对的数据结构,我们可以通过它的数据成员first访问key,通过访问它的数据成员second访问value。

      

       真正的值类型的定义如下:

      

       直译过来为映射类型,跟传统的值类型的翻译有点不一样。不过为了符合大家的习惯,在本篇文章中还是用传统的键值对代表value_type,用值类型代表mapped_type。

       返回:pair<iterator,bool>。返回的是一个键值对。其中iterator表示元素在map中的迭代器,bool表示插入是否成功。如果成功的话为true,失败则为false。需要注意的是,如果插入失败的话,iterator表示该键值元素在map中的迭代器。

       

       让我们再来看一下第二个版本的插入操作:

        

       参数:position。表示在插入的时候,会与map中首先比较元素的迭代器。通过前面的介绍我们知道,向map中插入元素的时候,插入的元素会和map中的元素进行比较,如果没有相同的键,才将元素插入到map中。通过传入position,我们可以定义待插入的元素会和map中哪一个元素首先进行比较,以此来提高我们的插入效率。当然,该参数不能胡乱填写。如果胡乱填写的话,会引起效率的损失。

       参数:x。同上。

       返回:iterator。新插入元素的位置。同上。

 

       第三个版本的插入操作:

      

       参数:first。要插入map中序列迭代器的开头(包含开头元素)。

       参数:last。要插入map中序列迭代器的结尾(不包含结尾元素)。

       注意InputIterator所指向的元素类型应为value_type。

      

       下面再让我们来看一看另外一个也拥有插入功能的操作

       

        说明:当该操作作为右值的时候,会得到该键值对应的值。当该操作作为左值的时候,如果要插入的键不存在,则会将新的键值对插入到map中。如果插入的键存在,则会修改键所对应的值、

 

       下面让我们来看一看使用这三个版本插入操作和operator[]操作的例子:

       

 

        下面四个为map的迭代器函数

       

        说明:这几个函数分别获取map的开始、结尾、逆向开始、逆向结尾的迭代器。只是需要注意的是,map作为一种关联容器,其开始迭代器/逆向开始迭代器并不一定就是指向插入map中的第一个/最后一个元素,而是指向按照规则comp由小到大排序的最小/最大元素。

       

        下面再让我们来看一下在map中比较常用的几个操作:

           

        说明:搜索整个map,判断键值x是否在map中存在。

        参数:x。待搜索的键值。

        返回:成功返回指向键值为x的元素的迭代器,失败返回map::end()。

 

       

        说明:删除操作。第一个版本在map中删除指向position的元素。第二个版本删除map中key的值为x的元素。第三个版本删除迭代器first(包含)到last(不包含)之间的所有元素。

        参数:position。指向待删除元素的迭代器。

        参数:x。待删除元素的键值。

        参数:first。指向待删除序列头的迭代器。

        参数:last。指向待删除序列尾的迭代器。

        返回:只有第二个版本的删除操作有返回值。其返回值表示在map中删除键值为x的元素个数,该值在map中只能为1。

 

        find和erase的使用例子如下所示:

         

 

        下面是我兑现前面承诺的时候,这里我为大家举一个使用自定义comp对象的例子:

       

 

        map中常用的操作大概就是这些了,当然还有一些在map中不怎么常用或者没有什么意义的操作在这里没有介绍,有兴趣的同学可以自己去看一下。