C++ STL map 详解


关联式容器的一种,map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括 C++ 基本数据类型(int、double 等)、 结构体类自定义的类型
通常情况下,map 容器中存储的各个键值对都选用 string 字符串作为键的类型。

map 容器

  1. 容器会自动根据各键值对的键的大小,对键值对做升序排序(默认)。
    即map 容器选用std::less对键值对升序排序。也可以手动指定 map 容器的排序规则(比如std::greater),也可以自定义排序规则。
  2. 存储的键值对,键的值都是唯一的、独一无二的。

一、map 容器定义

引入#include <map>
map 容器的模板定义

template < class Key,      // 指定键(key)的类型
    class T,        // 指定值(value)的类型
    class Compare = less<Key>,        // 指定排序规则(默认升序排列)
    class Alloc = allocator<pair<const Key,T> > // 指定分配器对象的类型
    > class map;

map 容器模板有 4 个参数,其中后 2 个参数都设有默认值。
我们只需要设定前 2 个参数的值,有些场景可能会用到第 3 个参数,但最后一个参数几乎不会用到。

创建C++ map容器的几种方法
map 容器的模板类中包含多种构造函数,下面就几种常用的创建 map 容器的方法:
map 容器中存储的键值对,其本质都是 pair 类模板创建的 pair 对象
map 容器的拷贝(复制)构造函数,即可成功创建一个和 myMap 完全一样的 newMap 容器。

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

std::map<std::string, int> myMap;                    //默认构造函数
std::map<std::string, int> myMap{ {"zhangsan",100},{"lisi",90} }; //声明同时初始化

// pair 类模板创建
std::map<std::string, int>myMap{std::make_pair("yuwen",80),std::make_pair("shuxue",70)}; 

//调用拷贝(复制)构造函数,创建的 newMap 容器与myMap 完全一样。
std::map<std::string, int>newMap(myMap);

// 取已建 map 容器中指定区域内的键值对,创建并初始化新的 map 容器
std::map<std::string, int>newMap(++myMap.begin(), myMap.end());

//手动修改了 myMap 容器为降序排序
std::map<std::string, int, std::greater<std::string> >myMap{ {"zhangsan",100},{"lisi",90} };

//移动构造函数
std::map<std::string,int> disMap() {
    std::map<std::string, int>tempMap{ {"zhangsan",100},{"lisi",90} };
    return tempMap;
}
//调用 map 类模板的移动构造函数创建 newMap 容器
std::map<std::string, int>newMap(disMap());

注意:无论是调用复制构造函数还是调用拷贝构造函数,都必须保证这 2 个容器的类型完全一致。

二、map 容器成员方法

成员方法功能
begin()返回指向容器中 (已排好序)第一个键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器 (已排好序)最后一个元素所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()功能同begin() ,则该方法返回的是 const 类型的反向双向迭代器。
rend()功能同 end() ,则该方法返回的是 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 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
cout(key)在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。

小案例:

#include "stdafx.h"
#include <map>
#include <iostream>
#include <string>
#include <functional>
using namespace std;


int main()
{
	std::map<std::string, int, std::greater<std::string>> mymap;

	mymap.emplace("zhangsan", 90);
	mymap.emplace("lisi", 89);
	mymap.emplace("wangwu", 87);
	cout << "mymap.size():" << mymap.size() << endl;
	for (auto it = mymap.begin(); it != mymap.end(); it++) 
	{
		cout << it->first << " " << it->second << endl;
	}
    return 0;
}

报错:C++ “greater”: 未声明的标识符错误
引入头文件:#include<functional> 即可解决

三、map 类元素删除

map 类模板提供了 erase() 和 clear() 成员方法,可用来删除容器中存储的键值对。

erase() 有 3 种适用于不同实际场景需要的语法格式:

  1. 可以根据目标键值对位于 map 容器中的位置,实现删除该键值对的目的。
    //删除 map 容器中迭代器指定位置的键值对
    iterator erase (const_iterator position);
    position 为迭代器,指向要删除的键值对。同时该方法会返回一个 iterator 迭代器,其指向的是删除键值对之后的那个键值对。(等同于 end() 成员方法返回的迭代器)

  2. 传入目标键值对的 ,这个与python一样。
    //删除 map 容器中键为 k 的键值对
    size_type erase (const key_type& k)
    返回值为成功删除的键值对的个数;

  3. 删除某个指定区域内的所有键值对
    //删除 map 容器中位于 [first,last) 区域内的所有键值对
    iterator erase (const_iterator first, const_iterator last);
    返回的迭代器将指向 map 容器最后一个键值对之后的位置(等同于 end() 成员方法返回的迭代器)。

小案例:

#include <iostream>
#include <map>      // map
#include <string>   // string
using namespace std;

int main() {
    map<std::string, std::string>myMap{ {"zhangsan", "今天去购物"},
                                        {"lisi", "今天去游泳"},
                                        {"wangwu", "今天去爬山"},
                                        {"zhaoliu", "今天去读书"} };
                                        
    map<std::string, std::string>Map02{ {"zhangsan02", "今天去购物"},
                                        {"lisi02", "今天去游泳"},
                                        {"wangwu02", "今天去爬山"},
                                        {"zhaoliu02", "今天去读书"} };

    //创建一个指向要删除的键值对的迭代器(这里指向第二个键值对)
    map<string, string>::iterator iter = ++myMap.begin();
    map<string, string>::iterator ret = myMap.erase(iter);     //执行删除操作
    //输出 erase() 方法返回的迭代器指向的键值对(等同于 end() 成员方法返回的迭代器)
    cout << ret->first << " " << ret->second << endl;         // wangwu 今天去爬山
    
    
    int num = myMap.erase("zhaoliu");                          //执行删除操作
    cout << "num = " << num << endl;                           // num = 1 (成功删除的键值对的个数)  


    map<string, string>::iterator first02 = Map02.begin();
    map<string, string>::iterator last02 = --Map02.end();      //--Map02.end() 向前移一位
    map<string, string>::iterator ret02 = Map02.erase(first02,last02);
    cout << ret02->first << " " << ret02->second << endl;      // zhaoliu02, 今天去读书
    return 0;
}

void clear() 清空容器。该方法不需要传入任何参数,也不需要接收任何返回值。
MapName.clear();

http://c.biancheng.net/view/7187.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值