STL关联容器详解之map

本文详细介绍了C++ STL 中的map容器,包括其存储结构、初始化方法、常用成员函数如begin()、end()、find()、insert()等。map容器用于存储键值对,其内部按键的排序规则自动组织数据。文章通过实例展示了map的创建、遍历、查找和插入操作,并对比了multimap容器的特点。
摘要由CSDN通过智能技术生成

参考链接

map容器

map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括 C++ 基本数据类型(int、double 等)、使用结构体或类自定义的类型。

通常情况下,map 容器中存储的各个键值对都选用 string 字符串作为键的类型。在使用 map 容器存储多个键值对时,该容器会自动根据各键值对的键的大小,按照既定的规则进行排序。

默认情况下,map 容器选用std::less<T>排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值对做升序排序。当然,根据实际情况的需要,我们可以手动指定 map 容器的排序规则,既可以选用 STL 标准库中提供的其它排序规则(比如std::greater<T>),也可以自定义排序规则。

使用 map 容器存储的各个键值对,键的值既不能重复也不能被修改。换句话说,map 容器中存储的各个键值对不仅键的值独一无二,键的类型也会用 const 修饰

创建map容器的几种方法

  • 通过调用 map 容器类的默认构造函数,可以创建出一个空的 map 容器:

    std::map<std::string, int>myMap;
    
  • 在创建 map 容器的同时,也可以进行初始化:

    std::map<std::string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
    std::map<std::string, int>myMap{std::make_pair("C语言教程",10),std::make_pair("STL教程",20)};
    
  • 利用先前已创建好的 map 容器,再创建一个新的 map 容器:

    std::map<std::string, int>newMap(myMap);
    

    当有临时的 map 对象作为参数,传递给要初始化的 map 容器时,此时就会调用移动构造函数

    #创建一个会返回临时 map 对象的函数
    std::map<std::string,int> disMap() {
        std::map<std::string, int>tempMap{ {"C语言教程",10},{"STL教程",20} };
        return tempMap;
    }
    //调用 map 类模板的移动构造函数创建 newMap 容器
    std::map<std::string, int>newMap(disMap());
    
  • 取已建 map 容器中指定区域内的键值对,创建并初始化新的 map 容器

    std::map<std::string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
    std::map<std::string, int>newMap(++myMap.begin(), myMap.end());
    
  • 手动修改了 myMap 容器的排序规则,令其作降序排序

    std::map<std::string, int, std::greater<std::string> >myMap{ {"C语言教程",10},{"STL教程",20} };
    

C++ map容器的成员方法

成员方法功能
begin()返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend()返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
find(key)在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
lower_bound(key)返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(key)返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
equal_range(key)该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。
empty()若容器为空,则返回 true;否则 false。
size()返回当前 map 容器中存有键值对的个数。
max_size()返回 map 容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。
operator[]map容器重载了 [] 运算符,只要知道 map 容器中某个键值对的键的值,就可以向获取数组中元素那样,通过键直接获取对应的值。
at(key)找到 map 容器中 key 键对应的值,如果找不到,该函数会引发 out_of_range 异常。
insert()向 map 容器中插入键值对。
erase()删除 map 容器指定位置、指定键(key)值或者指定区域内的键值对。后续章节还会对该方法做重点讲解。
swap()交换 2 个 map 容器中存储的键值对,这意味着,操作的 2 个键值对的类型必须相同。
clear()清空 map 容器中所有的键值对,即使 map 容器的 size() 为 0。
emplace()在当前 map 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。
emplace_hint()在本质上和 emplace() 在 map 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
count(key)在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。
#include <iostream>
#include <map>      // map
#include <string>       // string
using namespace std;
int main() {
    //创建空 map 容器,默认根据个键值对中键的值,对键值对做降序排序
    std::map<std::string, std::string, std::greater<std::string>>myMap;
    //调用 emplace() 方法,直接向 myMap 容器中指定位置构造新键值对
    myMap.emplace("C语言教程","http://c.biancheng.net/c/");
    myMap.emplace("Python教程", "http://c.biancheng.net/python/");
    myMap.emplace("STL教程", "http://c.biancheng.net/stl/");
    //输出当前 myMap 容器存储键值对的个数
    cout << "myMap size==" << myMap.size() << endl;
    //判断当前 myMap 容器是否为空
    if (!myMap.empty()) {
        //借助 myMap 容器迭代器,将该容器的键值对逐个输出
        for (auto i = myMap.begin(); i != myMap.end(); ++i) {
            cout << i->first << " " << i->second << endl;
        }
    }  
    return 0;
}

map容器迭代器

C++ STL 标准库为 map 容器配备的是双向迭代器(bidirectional iterator)。这意味着,map 容器迭代器只能进行 ++p、p++、–p、p–、*p 操作,并且迭代器之间只能使用 == 或者 != 运算符进行比较。
begin()/end()组合为例,演示了如何遍历 map 容器:

#include <iostream>
#include <map>      // pair
#include <string>       // string
using namespace std;
int main() {
    //创建并初始化 map 容器
    std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},{"C语言教程","http://c.biancheng.net/c/"} };
    //调用 begin()/end() 组合,遍历 map 容器
    for (auto iter = myMap.begin(); iter != myMap.end(); ++iter) {
        cout << iter->first << " " << iter->second << endl;
    }
    return 0;
}

map 类模板中还提供了 find()成员方法,它能帮我们查找指定 key 值的键值对,如果成功找到,则返回一个指向该键值对的双向迭代器;反之,其功能和 end() 方法相同。

#include <iostream>
#include <map>      // pair
#include <string>       // string
using namespace std;
int main() {
    //创建并初始化 map 容器
    std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},
                                             {"C语言教程","http://c.biancheng.net/c/"},
                                             {"Java教程","http://c.biancheng.net/java/"} };
    //查找键为 "Java教程" 的键值对
    auto iter = myMap.find("Java教程");
    //从 iter 开始,遍历 map 容器
    for (; iter != myMap.end(); ++iter) {
        cout << iter->first << " " << iter->second << endl;
    }
    return 0;
}

map 类模板中还提供有lower_bound(key)upper_bound(key)成员方法,它们的功能是类似的,唯一的区别在于:

  • lower_bound(key) 返回的是指向第一个键不小于 key 的键值对的迭代器;
  • upper_bound(key) 返回的是指向第一个键大于 key 的键值对的迭代器;
#include <iostream>
#include <map>      // pair
#include <string>       // string
using namespace std;
int main() {
    //创建并初始化 map 容器
    std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},
                                             {"C语言教程","http://c.biancheng.net/c/"},
                                             {"Java教程","http://c.biancheng.net/java/"} };
    //找到第一个键的值不小于 "Java教程" 的键值对
    auto iter = myMap.lower_bound("Java教程");
    cout << "lower:" << iter->first << " " << iter->second << endl;
   
    //找到第一个键的值大于 "Java教程" 的键值对
    iter = myMap.upper_bound("Java教程");
    cout <<"upper:" << iter->first << " " << iter->second << endl;
    return 0;
}

lower_bound(key) 和 upper_bound(key) 更多用于 multimap 容器,在 map 容器中很少用到。

equal_range(key)成员方法可以看做是 lower_bound(key) 和 upper_bound(key) 的结合体,该方法会返回一个 pair 对象,其中的 2 个元素都是迭代器类型,其中 pair.first 实际上就是 lower_bound(key) 的返回值,而 pair.second 则等同于 upper_bound(key) 的返回值。
equal_range(key) 成员方法表示的一个范围,位于此范围中的键值对,其键的值都为 key

#include <iostream>
#include <utility>  //pair
#include <map>      // map
#include <string>       // string
using namespace std;
int main() {
    //创建并初始化 map 容器
    std::map<string, string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},
                                   {"C语言教程","http://c.biancheng.net/c/"},
                                   {"Java教程","http://c.biancheng.net/java/"} };
    //创建一个 pair 对象,来接收 equal_range() 的返回值
    pair <std::map<string, string>::iterator, std::map<string, string>::iterator> myPair = myMap.equal_range("C语言教程");
    //通过遍历,输出 myPair 指定范围内的键值对
    for (auto iter = myPair.first; iter != myPair.second; ++iter) {
        cout << iter->first << " " << iter->second << endl;
    }
    return 0;
}

和 lower_bound(key)、upper_bound(key) 一样,该方法也更常用于 multimap 容器,因为 map 容器中各键值对的键的值都是唯一的,因此通过 map 容器调用此方法,其返回的范围内最多也只有 1 个键值对。

map获取键对应值的几种方法

  • map 类模板中对[ ]运算符进行了重载,通过指定的键,我们可以轻松获取 map 容器中该键对应的值。

    #include <iostream>
    #include <map>      // map
    #include <string>   // string
    using namespace std;
    int main() {
        //创建并初始化 map 容器
        std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},
                                                 {"C语言教程","http://c.biancheng.net/c/"},
                                                 {"Java教程","http://c.biancheng.net/java/"} };
        string cValue = myMap["C语言教程"];
        cout << cValue << endl;
        return 0;
    }
    

    若当前 map 容器中没有包含该指定键的键值对,则此时使用 [ ] 运算符将不再是访问容器中的元素,而变成了向该 map 容器中增添一个键值对。

    #include <iostream>
    #include <map>      // map
    #include <string>   // string
    using namespace std;
    int main() {
        //创建空 map 容器
        std::map<std::string, int>myMap;
        int cValue = myMap["C语言教程"];
        for (auto i = myMap.begin(); i != myMap.end(); ++i) {
            cout << i->first << " "<< i->second << endl;
        }
        return 0;
    }
    
  • 使用 at() 成员方法,需要根据指定的键,才能从容器中找到该键对应的值;如果在当前容器中查找失败,该方法不会向容器中添加新的键值对,而是直接抛出 out_of_range 异常。

    #include <iostream>
    #include <map>      // map
    #include <string>   // string
    using namespace std;
    int main() {
        //创建并初始化 map 容器
        std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},
                                                 {"C语言教程","http://c.biancheng.net/c/"},
                                                 {"Java教程","http://c.biancheng.net/java/"} };
        cout << myMap.at("C语言教程") << endl;
        //下面一行代码会引发 out_of_range 异常
        //cout << myMap.at("Python教程") << endl;
        return 0;
    }
    
  • 借助 find() 成员方法间接实现此目的

    #include <iostream>
    #include <map>      // map
    #include <string>   // string
    using namespace std;
    int main() {
        //创建并初始化 map 容器
        std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},
                                                 {"C语言教程","http://c.biancheng.net/c/"},
                                                 {"Java教程","http://c.biancheng.net/java/"} };
        map< std::string, std::string >::iterator myIter = myMap.find("C语言教程");
        cout << myIter->first << " " << myIter->second << endl;
        return 0;
    }
    

    如果 find() 查找失败,会导致第 13 行代码运行出错。因为当 find() 方法查找失败时,其返回的迭代器指向的是容器中最后一个键值对之后的位置,即不指向任何有意义的键值对,也就没有所谓的 first 和 second 成员了。

  • 遍历整个 map 容器,找到包含指定键的键值对,进而获取该键对应的值。

    #include <iostream>
    #include <map>      // map
    #include <string>   // string
    using namespace std;
    int main() {
        //创建并初始化 map 容器
        std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"},
                                                 {"C语言教程","http://c.biancheng.net/c/"},
                                                 {"Java教程","http://c.biancheng.net/java/"} };
        for (auto iter = myMap.begin(); iter != myMap.end(); ++iter) {
            //调用 string 类的 compare() 方法,找到一个键和指定字符串相同的键值对
            if (!iter->first.compare("C语言教程")) {
                cout << iter->first << " " << iter->second << endl;
            }
        }
        return 0;
    }
    

map insert()插入数据的4种方式

insert() 方法可以将新的键值对插入到 map 容器中的指定位置,但这与 map 容器会自动对存储的键值对进行排序并不冲突。当使用 insert() 方法向 map 容器的指定位置插入新键值对时,其底层会先将新键值对插入到容器的指定位置,如果其破坏了 map 容器的有序性,该容器会对新键值对的位置进行调整。

  • 无需指定插入位置,直接将键值对添加到 map 容器中。

    //1、引用传递一个键值对
    pair<iterator,bool> insert (const value_type& val);
    //2、以右值引用的方式传递键值对
    template <class P>
        pair<iterator,bool> insert (P&& val);
    

    其中,val 参数表示键值对变量,同时该方法会返回一个 pair 对象,其中 pair.first 表示一个迭代器,pair.second 为一个 bool 类型变量:

    • 如果成功插入 val,则该迭代器指向新插入的 val,bool 值为 true;
    • 如果插入 val 失败,则表明当前 map 容器中存有和 val 的键相同的键值对(用 p 表示),此时返回的迭代器指向 p,bool 值为 false。
    #include <iostream>
    #include <map>  //map
    #include <string> //string
    using namespace std;
    int main()
    {
        //创建一个空 map 容器
        std::map<string, string> mymap;
       
        //创建一个真实存在的键值对变量
        std::pair<string, string> STL = { "STL教程","http://c.biancheng.net/stl/" };
       
        //创建一个接收 insert() 方法返回值的 pair 对象
        std::pair<std::map<string, string>::iterator, bool> ret;
       
        //插入 STL,由于 STL 并不是临时变量,因此会以第一种方式传参
        ret = mymap.insert(STL);
        cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
        //以右值引用的方式传递临时的键值对变量
        ret = mymap.insert({ "C语言教程","http://c.biancheng.net/c/" });
        cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
        //插入失败样例
        ret = mymap.insert({ "STL教程","http://c.biancheng.net/java/" });
        cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
        return 0;
    }
    
  • insert() 方法还支持向 map 容器的指定位置插入新键值对

    //以普通引用的方式传递 val 参数
    iterator insert (const_iterator position, const value_type& val);
    //以右值引用的方式传递 val 键值对参数
    template <class P>
        iterator insert (const_iterator position, P&& val);
    

    其中 val 为要插入的键值对变量。注意,和第 1 种方式的语法格式不同,这里 insert() 方法返回的是迭代器,而不再是 pair 对象:

    • 如果插入成功,insert() 方法会返回一个指向 map 容器中已插入键值对的迭代器;
    • 如果插入失败,insert() 方法同样会返回一个迭代器,该迭代器指向 map 容器中和 val 具有相同键的那个键值对。
    #include <iostream>
    #include <map>  //map
    #include <string> //string
    using namespace std;
    int main()
    {
        //创建一个空 map 容器
        std::map<string, string> mymap;
       
        //创建一个真实存在的键值对变量
        std::pair<string, string> STL = { "STL教程","http://c.biancheng.net/stl/" };
        //指定要插入的位置
        std::map<string, string>::iterator it = mymap.begin();
        //向 it 位置以普通引用的方式插入 STL
        auto iter1 = mymap.insert(it, STL);
        cout << iter1->first << " " << iter1->second << endl;
        //向 it 位置以右值引用的方式插入临时键值对
        auto iter2 = mymap.insert(it, std::pair<string, string>("C语言教程", "http://c.biancheng.net/c/"));
        cout << iter2->first << " " << iter2->second << endl;
        //插入失败样例
        auto iter3 = mymap.insert(it, std::pair<string, string>("STL教程", "http://c.biancheng.net/java/"));
        cout << iter3->first << " " << iter3->second << endl;
        return 0;
    }
    

    即便指定了新键值对的插入位置,map 容器仍会对存储的键值对进行排序。也可以说,决定新插入键值对位于 map 容器中位置的,不是 insert() 方法中传入的迭代器,而是新键值对中键的值。

  • 支持向当前 map 容器中插入其它 map 容器指定区域内的所有键值对

    template <class InputIterator>
      void insert (InputIterator first, InputIterator last);
    

    其中 first 和 last 都是迭代器,它们的组合<first,last>可以表示某 map 容器中的指定区域。

    #include <iostream>
    #include <map>  //map
    #include <string> //string
    using namespace std;
    int main()
    {
        //创建并初始化 map 容器
        std::map<std::string, std::string>mymap{ {"STL教程","http://c.biancheng.net/stl/"},
                                                    {"C语言教程","http://c.biancheng.net/c/"},
                                                    {"Java教程","http://c.biancheng.net/java/"} };
        //创建一个空 map 容器
        std::map<std::string, std::string>copymap;
        //指定插入区域
        std::map<string, string>::iterator first = ++mymap.begin();
        std::map<string, string>::iterator last = mymap.end();
        //将<first,last>区域内的键值对插入到 copymap 中
        copymap.insert(first, last);
        //遍历输出 copymap 容器中的键值对
        for (auto iter = copymap.begin(); iter != copymap.end(); ++iter) {
            cout << iter->first << " " << iter->second << endl;
        }
        return 0;
    }
    
  • insert() 方法还允许一次向 map 容器中插入多个键值对

    void insert ({val1, val2, ...});
    
    #include <iostream>
    #include <map>  //map
    #include <string> //string
    using namespace std;
    int main()
    {
        //创建空的 map 容器
        std::map<std::string, std::string>mymap;
        //向 mymap 容器中添加 3 个键值对
        mymap.insert({ {"STL教程", "http://c.biancheng.net/stl/"},
                       { "C语言教程","http://c.biancheng.net/c/" },
                       { "Java教程","http://c.biancheng.net/java/" } });
        for (auto iter = mymap.begin(); iter != mymap.end(); ++iter) {
            cout << iter->first << " " << iter->second << endl;
        }
        return 0;
    }
    

emplace()和emplace_hint()

实现相同的插入操作,无论是用 emplace() 还是 emplace_hont(),都比 insert() 方法的效率高.

emplace()

template <class... Args>
  pair<iterator,bool> emplace (Args&&... args);

参数 (Args&&… args) 指的是,这里只需要将创建新键值对所需的数据作为参数直接传入即可,此方法可以自行利用这些数据构建出指定的键值对。另外,该方法的返回值也是一个 pair 对象,其中 pair.first 为一个迭代器,pair.second 为一个 bool 类型变量:

  • 当该方法将键值对成功插入到 map 容器中时,其返回的迭代器指向该新插入的键值对,同时 bool 变量的值为 true;
  • 当插入失败时,则表明 map 容器中存在具有相同键的键值对,此时返回的迭代器指向此具有相同键的键值对,同时 bool 变量的值为 false。
#include <iostream>
#include <map>  //map
#include <string> //string
using namespace std;
int main()
{
    //创建并初始化 map 容器
    std::map<string, string>mymap;
    //插入键值对
    pair<map<string, string>::iterator, bool> ret = mymap.emplace("STL教程", "http://c.biancheng.net/stl/");
    cout << "1、ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
    //插入新键值对
    ret = mymap.emplace("C语言教程", "http://c.biancheng.net/c/");
    cout << "2、ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
    //失败插入的样例
    ret = mymap.emplace("STL教程", "http://c.biancheng.net/java/");
    cout << "3、ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
    return 0;
}

emplace_hint()

template <class... Args>
  iterator emplace_hint (const_iterator position, Args&&... args);

显然和 emplace() 语法格式相比,有以下 2 点不同:

  • 该方法不仅要传入创建键值对所需要的数据,还需要传入一个迭代器作为第一个参数,指明要插入的位置(新键值对键会插入到该迭代器指向的键值对的前面);
  • 该方法的返回值是一个迭代器,而不再是 pair 对象。当成功插入新键值对时,返回的迭代器指向新插入的键值对;反之,如果插入失败,则表明 map 容器中存有相同键的键值对,返回的迭代器就指向这个键值对。
#include <iostream>
#include <map>  //map
#include <string> //string
using namespace std;
int main()
{
    //创建并初始化 map 容器
    std::map<string, string>mymap;
    //指定在 map 容器插入键值对
    map<string, string>::iterator iter = mymap.emplace_hint(mymap.begin(),"STL教程", "http://c.biancheng.net/stl/");
    cout << iter->first << " " << iter->second << endl;
    iter = mymap.emplace_hint(mymap.begin(), "C语言教程", "http://c.biancheng.net/c/");
    cout << iter->first << " " << iter->second << endl;
    //插入失败样例
    iter = mymap.emplace_hint(mymap.begin(), "STL教程", "http://c.biancheng.net/java/");
    cout << iter->first << " " << iter->second << endl;
    return 0;
}

multimap容器

和 map 容器的区别在于,multimap 容器中可以同时存储多(≥2)个键相同的键值对。
实现 multimap 容器的类模板也定义在<map>头文件,并位于 std 命名空间中。

创建multimap容器的方法

  • 通过调用 multimap 类模板的默认构造函数,可以创建一个空的 multimap 容器:

    std::multimap<std::string, std::string>mymultimap;
    
  • 在创建 multimap 容器的同时,还可以进行初始化操作。

    //创建并初始化 multimap 容器
    multimap<string, string>mymultimap{ {"C语言教程", "http://c.biancheng.net/c/"},
                                        {"Python教程", "http://c.biancheng.net/python/"},
                                        {"STL教程", "http://c.biancheng.net/stl/"} };
    //借助 pair 类模板的构造函数来生成各个pair类型的键值对
    multimap<string, string>mymultimap{
        pair<string,string>{"C语言教程", "http://c.biancheng.net/c/"},
        pair<string,string>{ "Python教程", "http://c.biancheng.net/python/"},
        pair<string,string>{ "STL教程", "http://c.biancheng.net/stl/"}
    };
    //调用 make_pair() 函数,生成键值对元素
    //创建并初始化 multimap 容器
    multimap<string, string>mymultimap{
        make_pair("C语言教程", "http://c.biancheng.net/c/"),
        make_pair("Python教程", "http://c.biancheng.net/python/"),
        make_pair("STL教程", "http://c.biancheng.net/stl/")
    };
    
  • 调用 multimap 类模板的拷贝(复制)构造函数,也可以初始化新的 multimap 容器:

    multimap<string, string>newmultimap(mymultimap);
    

    当有临时的 multimap 容器作为参数初始化新 multimap 容器时,其底层就会调用移动构造函数来实现初始化操作。

    //创建一个会返回临时 multimap 对象的函数
    multimap<string, string> dismultimap() {
        multimap<string, string>tempmultimap{ {"C语言教程", "http://c.biancheng.net/c/"},{"Python教程", "http://c.biancheng.net/python/"} };
        return tempmultimap;
    }  
    //调用 multimap 类模板的移动构造函数创建 newMultimap 容器
    multimap<string, string>newmultimap(dismultimap());
    
  • 从已有 multimap 容器中,选定某块区域内的所有键值对,用作初始化新 multimap 容器时使用。

    //创建并初始化 multimap 容器
    multimap<string, string>mymultimap{ {"C语言教程", "http://c.biancheng.net/c/"},
                                        {"Python教程", "http://c.biancheng.net/python/"},
                                        {"STL教程", "http://c.biancheng.net/stl/"} };
    multimap<string, string>newmultimap(++mymultimap.begin(), mymultimap.end());
    
  • 利用了 STL 模板库提供的std::greater<T>排序函数,实现令 multimap 容器对存储的键值对做降序排序:

    multimap<char, int, std::greater<char>>mymultimap{ {'a',1},{'b',2} };
    

multimap容器的成员方法

成员方法功能
begin()返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 multimap 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 multimap 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 multimap 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend()返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 multimap 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
find(key)在 multimap 容器中查找首个键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 multimap 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
lower_bound(key)返回一个指向当前 multimap 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 multimap 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(key)返回一个指向当前 multimap 容器中第一个大于 key 的键值对的迭代器。如果 multimap 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
equal_range(key)该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对。
empty()若容器为空,则返回 true;否则 false。
size()返回当前 multimap 容器中存有键值对的个数。
max_size()返回 multimap 容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。
insert()向 multimap 容器中插入键值对。
erase()删除 multimap 容器指定位置、指定键(key)值或者指定区域内的键值对。
swap()交换 2 个 multimap 容器中存储的键值对,这意味着,操作的 2 个键值对的类型必须相同。
clear()清空 multimap 容器中所有的键值对,使 multimap 容器的 size() 为 0。
emplace()在当前 multimap 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。
emplace_hint()在本质上和 emplace() 在 multimap 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
count(key)在当前 multimap 容器中,查找键为 key 的键值对的个数并返回。

和 map 容器相比,multimap 未提供 at() 成员方法,也没有重载 [] 运算符。这意味着,map 容器中通过指定键获取指定指定键值对的方式,将不再适用于 multimap 容器。其实这很好理解,因为 multimap 容器中指定的键可能对应多个键值对,而不再是 1 个。

#include <iostream>
#include <map>  //map
using namespace std;   
int main()
{
    //创建并初始化 multimap 容器
    multimap<char, int>mymultimap{ {'a',10},{'b',20},{'b',15}, {'c',30} };
    //输出 mymultimap 容器存储键值对的数量
    cout << mymultimap.size() << endl;
    //输出 mymultimap 容器中存储键为 'b' 的键值对的数量
    cout << mymultimap.count('b') << endl;
    for (auto iter = mymultimap.begin(); iter != mymultimap.end(); ++iter) {
        cout << iter->first << " " << iter->second << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值