首页 > 编程语言 > 详细

C++中map的基本操作

时间:2020-03-04 16:05:20      阅读:84      评论:0      收藏:0      [点我收藏+]

map

在STL的头文件中map中定义了模版类map和multimap,用有序二叉树表存储类型为pair<const Key, T>的元素对序列。序列中的元素以const Key部分作为标识,map中所有元素的Key值必须是唯一的,multimap则允许有重复的Key值。可以将map看作是由Key标识元素的元素集合,这类容器也被称为“关联容器”,可以通过一个Key值来快速决定一个元素,因此非常适合于需要按照Key值查找元素的容器。

定义map对象的代码示例:

map<string, int> m;

 

在介绍关联容器操作之前,先了解一下pair的标准库类型。pair类型是在有文件utility中定义的,pair是将2个数据组合成一组数据,当需要这样的需求时就可以使用pair,如STL中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。 pair的实现是一个结构体,主要的两个成员变量是first ,second 因为是使用struct不是class,所以可以直接使用pair的成员变量。


pair类型包含了两个数据值,通常有以下的一些定义和初始化的一些方法:

pair<T1, T2> p;         //定义了一个空的pair对象p,T1和T2的成员都进行了值初始化
pair<T1, T2> p(v1, v2); // p是一个成员类型为T1和T2的pair; first和second成员分别用v1和v2进行初始化。
make_pair(v1, v2);      //以v1和v2值创建的一个新的pair对象

 

map的基本操作 

 

向map中插入元素 

m[key] = value;

m.insert(make_pair(key, value));                               

[key]操作是map很有特色的操作,如果在map中存在键值为key的元素对, 则返回该元素对的值域部分,否则将会创建一个键值为key的元素对,值域为默认值。所以可以用该操作向map中插入元素对或修改已经存在的元素对的值域部分。

也可以直接调用insert方法插入元素对,insert操作会返回一个pair,当map中没有与key相匹配的键值时,其first是指向插入元素对的迭代器,其second为true;若map中已经存在与key相等的键值时,其first是指向该元素对的迭代器,second为false。

即,insert可能插入失败,用一下代码可以检查是否插入成功:

pair<map<key,value >::iterator, bool> Insert_Pair;
Insert_Pair = m.insert(make_pair(key, value));
if(!Insert_Pair.second)
cout << ""Error insert new element" << endl;

查找元素 

int i = m[key];

要注意的是,当与该键值相匹配的元素对不存在时,会创建键值为key(当另一个元素是整形时,m[key]=0)的元素对。

map<key, value>::iterator it = m.find(key);

如果map中存在与key相匹配的键值时,find操作将返回指向该元素对的迭代器,否则,返回的迭代器等于map的end()(参见vector中提到的begin()和end()操作)。

删除元素 

m.erase(key);

删除与指定key键值相匹配的元素对,并返回被删除的元素的个数。

m.erase(it);

有的说m.erase(it)返回指向像一个元素的迭代器,但我的实际操作发现返回的是void,一些博客也提到了这一点。建议是当作返回void使用...

要注意进行安全的删除操作!

错误示范:

for(map<key,value >::iterator iter=m.begin();iter!=m.end();++iter)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter);
}

这是一种错误的写法,会导致程序行为不可知.究其原因是map 是关联容器,对于关联容器来说,如果某一个元素已经被删除,那么其对应的迭代器就失效了,不应该再被使用;否则会导致程序无定义的行为。(但是有的博客用这种方法也能得出正确的结果,不过这里提到的无定义行为也有道理,先暂且将这种方法视为错误的方法吧)

正确示范:

for(map<key,value >::iterator iter=mapTest.begin();iter!=mapTest.end();)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter++);
}

这种删除方式也是STL源码一书中推荐的方式,分析 m.erase(it++)语句,map中在删除iter的时候,先将iter做缓存,然后执行iter++使之指向下一个结点,再进入erase函数体中执行删除操作,删除时使用的iter就是缓存下来的iter(也就是当前iter(做了加操作之后的iter)所指向结点的上一个结点)。

(m.erase(it++) )和(m.erase(it); iter++; )这个执行序列是不相同的。前者在erase执行前进行了加操作,在it被删除(失效)前进行了加操作,是安全的;后者是在erase执行后才进行加操作,而此时iter已经被删除(当前的迭代器已经失效了),对一个已经失效的迭代器进行加操作,行为是不可预期的,这种写法势必会导致 map操作的失败并引起进程的异常。

其他操作 

m.size();

返回元素个数

m.empty();

判断是否为空

m.clear(); 

清空所有元素

 

参考链接:

https://blog.csdn.net/forever__1234/article/details/89647975

https://blog.csdn.net/u010029439/article/details/89681773

https://xuanxuanblingbling.github.io/life/study/2019/03/20/STL/

https://www.cnblogs.com/zhoulipeng/p/3432009.html

https://www.cnblogs.com/kex1n/archive/2011/12/06/2278505.html

 

C++中map的基本操作

原文:https://www.cnblogs.com/wsshub/p/12408746.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!