map与multimap其实与set与multiset差不多,set与multiset是一种特殊的map与multimap。其再命名空间的定义如下:
namespace std{
template <class key, class t,
class compare = less<key>,
class allocator = allocator<pair<const key, t>>>
class map ;
template <class key, class t,
class compare = less<key>,
class allocator = allocator<pair<const key, t>>>
class multimap ;
}
其第一个参数是key,第二个参数是value,和所有标准的关联式容器一样,map/multimap也是平衡二叉树,set中value,key指向同一个对象,map元素是key/value的pair,map可以作为关联式数组使用,map也是通过key的值进行排序的,所以搜索元素有很好的性能,其key是const类型,不可以直接改变,要修改的话必须先删除这个元素,再插入一个新的,但value是可以改变的。
访问其中元素的方法如下:
std::map<std::string, float> coll ;
std::map<std::string, float>::iteraror pos ;
for (pos = coll.begin(); pos != coll.end(); ++pos)
{
std::cout << pos->first << pos->second ;
}
安插一个key/value pair的时候,在map/multimap内部,key被视为常数,所以要不提供正确的型别,要不提供隐式或显示型别转换,有个三个方法可以插入value到map
- 运用value_type
为了避免隐式的型别转换,可以运用value_type明白传递正确的型别,value_type是容器本省提供的型别定义
std::map<std::string, float> coll ;
coll.insert(std::map<std::string, float>::value_type("otto", 22.3)) ;
2.运用pair<>
std::map<std::string, float> coll ;
coll.insert(std::pair<std::string, float>("otto", 22.3)) ;
coll.insert(std::pair<const std::string, float>("otto", 22.3)) ;//这个类型不同,需要转换,insert需要定义成member template
3.运用make_pair
std::map<std::string, float> coll ;
coll.insert(std::make_pair("otto", 22.3)) ;//这个也需要member template来执行类别转换
map的insert函数的返回值和set差不多,也可以判断是否成功
这里有个关于迭代器失效的例子:
typedef std::map<std::string, float> StringFloatMap ;
StringFloatMap coll ;
StringFloatMap::iterator pos ;
for (pos = coll.begin(); pos != coll.end(); ++pos)
{
if (pos->second == value)
coll.erase(pos) ;//对pos所指元素实施erase(),会使pos成为一个有效的迭代器,如果不对他重新设置就是用,会出现未定义行为,一个++pos也是不行的
}
要是erase()能够返回下一个元素的位置,但是由于在关联容器中比较耗时,所以就没有这个特性,正确做法如下:
typedef std::map<std::string, float> StringFloatMap ;
StringFloatMap coll ;
StringFloatMap::iterator pos ;
for (pos = coll.begin(); pos != coll.end(); ++pos)
{
if (pos->second == value)
coll.erase(pos++) ;//pos会指向下一个元素,但返回指向原位置的一个副本,当调用erase时,pos已经不再指向即将被删除的元素了
else
++pos ;
}
这个好像有次面试遇到过
将map视为关联式数组,但其中有利有弊
利:方便,例如
std::map<std::sting, float> coll ;
coll["otto"] = 7.7 ;
如果没有键值为otto的元素,则首先调y用value的默认构造函数,然后将7.7赋值给value
弊:不小心插入一个元素,调用默认构造函数,然后重新赋值,这个速度比较慢
#include <iostream>
#include <map>
#include <string>
#include <iterator>
using namespace std;
int main()
{
typedef map<string, float> StringFloatMap ;//设置排序规则从大到小
StringFloatMap stocks ;
stocks["A"] = 2.3 ;
stocks["B"] = 2.4 ;
stocks["C"] = 2.5 ;
stocks["D"] = 2.6 ;
StringFloatMap::iterator pos ;
for (pos = stocks.begin(); pos != stocks.end(); ++pos)
{
cout <<"stock:"<< pos->first <<"\t"
<< "price:" << pos->second <<endl ;
}
stocks["E"] = stocks["A"] ;//添加一个键值为E的元素
stocks.erase("D") ;//删除键值为D的元素
for (pos = stocks.begin(); pos != stocks.end(); ++pos)
{
cout << "stock:" << pos->first <<"\t"
<< "price:" << pos->second <<endl ;
}
system("pause") ;
}
这里主要是应用了关联数组添加元素,erase删除元素