Map和Multimap将key/value pair当作元素,进行管理。它们可根据key的排序准则自动将元素进行排序。其声明如下
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;
}
内部结构如下图
和set一样,map具有很好的排序功能,当然你不能改变其key,因为破坏了正确次序。要修改元素的key,必须先移除拥有该key的元素,然后插入新的key/value.
template <typename T>
inline bool replace_key(T& c, const T::key_type& old_key, const T::key_value& new_key)
{
typename T::iterator pos;
pos = c.find(old_key);
if (pos != c.end())
{
c.insert(typename T::value_type(new_key,pos->second));
c.erase(pos);
return true;
}
else
return false;
}
注意由于maps可以用[]来存取元素,因此还可以这样来替换key
col["new_key"] = col["new_key"];
col.erase("old_keys");
map<string,float> col;
col.insert(map<string,float>::value_type("otto",22.3));
map<string,float> col;
//use implicit conversion
col.insert(pair<string,float>("otto",22.3));
//use no implicit conversion
col.insert(pair<const string,float>("otto",22.3));
map<string,float> col;
col.insert(make_pair("otto",22.3));
最方便的就是make_pair了,下面是个简单的例子,检查插入是否成功
map<string,float> col;
if ( col.insert(make_pair("shi",12.3)).second ) //插入成功
{
}
else//插入失败
如果想要移除拥有某个value元素,可以运用erase()可办到,其返回移除元素的个数,对于map来说不是0就是1
col.erase(key);
如果multimap内含有重复元素,你不能使用erase()来删除这些重复元素中的第一个(因为C++根本不知道删除的是哪一个),你可以这么做
multimap<string,int> col;
...
multimap<string,int>::iterator pos;
pos = col.find(key);
if (pos != key)
{
col.erase(key);
}
以下重要移除元素时,当你移除迭代器所指对象时,有一个很大的危险
map<string,int> col;
...
multimap<string,int>::iterator pos;
for (pos=col.begin(); pos != col.end(); ++pos)
{
if (pos->second == value)
col.erase(pos);
}
如果删除了pos,光是一个++pos就会产生未定义行为。
下面是移除“迭代器所指元素的正确做法”
map<string,int> col;
...
multimap<string,int>::iterator pos;
for (pos=col.begin(); pos != col.end();)
{
if (pos->second == value)
col.erase(pos++);
else
++pos;
}
至于为什么,只要懂得前置++和后置++的一看就明白了。
m[key];//返回一个reference,指向键值为key的元素,如果该元素不存在,就安插该元素
注意你不可能用上一个错误的索引,而容器中尚未存在对应元素,那么就会自动安插该元素,新元素的value会由default构造函数构造
1. 优点:很容易就可以安插元素
2. 缺点:很容易安插错误的元素
#include <iostream>
#include <map>
#include <iterator>
using namespace std;
int main(void)
{
map<string,float> stocks;
stocks["BASF"] = 369.50;
stocks["VW"] = 413.50;
stocks["Daimler"] = 819.00;
stocks["BMW"] = 834.00;
stocks["Simens"] = 842.20;
map<string,float>::iterator pos;
for (pos=stocks.begin(); pos!=stocks.end(); ++pos)
{
cout << "stocks: " << pos->first << "\t"
<< "prices: " << pos->second << endl;
}
cout << endl;
for (pos=stocks.begin(); pos!=stocks.end(); ++pos)
{
pos->second *= 2;
}
for (pos=stocks.begin(); pos!=stocks.end(); ++pos)
{
cout << "stocks: " << pos->first << "\t"
<< "prices: " << pos->second << endl;
}
stocks["Volk"] = stocks["VW"];
stocks.erase("VW");
return 0;
}
#include <iostream>
#include <map>
#include <iomanip>
using namespace std;
int main(void)
{
multimap<string,string> dict;
dict.insert(make_pair("day","Tag"));
dict.insert(make_pair("strange","Atuo"));
dict.insert(make_pair("smart","elegant"));
dict.insert(make_pair("trait","Merkmal"));
dict.insert(make_pair("strange","seltsam"));
dict.insert(make_pair("smart","klug"));
dict.insert(make_pair("clever","raffiniert"));
multimap<string,string>::iterator pos;
cout.setf (ios::left, ios::adjustfield);
cout << ' ' << setw(10) << "english "
<< "german " << endl;
cout << setfill('-') << setw(20) << " "
<< setfill(' ') << endl;
for (pos=dict.begin(); pos!=dict.end(); ++pos)
{
cout << ' ' << setw(10) << pos->first.c_str()
<< pos->second << endl;
}
cout << endl;
string word("smart");
cout << word << ": " << endl;
for (pos=dict.lower_bound(word); pos!=dict.upper_bound(word); ++pos)
{
cout << " " << pos->second << endl;
}
word = ("raffinert");
cout << word << ": " << endl;
for (pos=dict.begin(); pos!=dict.end(); ++pos)
{
if (pos->second == word)
cout << " " << pos->first << endl;
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <map>
#include <functional>
using namespace std;
template<typename K, typename V>
class value_equals
{
private:
V _val;
public:
value_equals(const V& val) : _val(val) {}
bool operator() (pair<const K,V> elem)
{
return elem.second == _val;
}
};
int main(void)
{
map<float,float> col;
map<float,float>::iterator pos;
col[1] = 7;
col[2] = 4;
col[3] = 2;
col[4] = 3;
col[5] = 6;
col[6] = 1;
col[7] = 3;
pos = col.find(3);
if (pos != col.end())
cout << pos->first << ":" << pos->second << endl;
pos = find_if(col.begin(),col.end(),value_equals<float,float>(3));
if (pos != col.end())
cout << pos->first << ":" << pos->second << endl;
return 0;
}
/* 上面是写了个仿函数, */
解法2:使用全局函数
#include <iostream>
#include <algorithm>
#include <map>
#include <functional>
using namespace std;
template<typename K, typename V>
bool my_equal(pair<const K,V> elem, V val)
{
return elem.second == val;
}
int main(void)
{
map<float,float> col;
map<float,float>::iterator pos;
col[1] = 7;
col[2] = 4;
col[3] = 2;
col[4] = 3;
col[5] = 6;
col[6] = 1;
col[7] = 3;
pos = col.find(3);
if (pos != col.end())
cout << pos->first << ":" << pos->second << endl;
pos = find_if(col.begin(),col.end(),bind2nd(ptr_fun(my_equal<float,float>),3));
if (pos != col.end())
cout << pos->first << ":" << pos->second << endl;
return 0;
}
/* 写个全局函数,然后使用ptr_fun()接口使之能够使用仿函数适配器 */