1.map
map的特性是,所有元素都会根据元素的键值自动被排序。map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一个元素被视为键值,第二个被视为实值。map不允许两个元素拥有相同的键值。
template<class T1,class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first; //public
T2 second; //public
pair():first(T1()),second(T2()){}
pair(const T1& a,const T2& b):first(a),second(b){}
};
通过map的迭代器修正元素的键值是不行的,因为map元素的键值关系到map元素的排列规则。修改元素的实值是可以的,因为map元素的实值并不影响元素的排列规则。因此,map iterators既不是一种constant iterators,也不是一种mutable iterators。
map拥有和list相同的某些性质:当客户端对它进行元素新增操作(insert)或者删除操作(erase)时,操作之前的所有迭代器,在操作完成之后都依然有效。
由于RB-tree是一种平衡二叉树搜索树,自动排序的效果很不错,所以标准的STL map即以RB-tree为底层机制。又由于map所开放的各种操作接口,RB-tree也都提供了,所以几乎所有的map操作行为,都只是转调用RB-tree的操作行为而已。
2.实例
#include <iostream>
#include <string>
#include <map>
typedef std::pair<int,std::string> ISPAIR;
typedef std::map<int,std::string> ISMAP;
int main()
{
///1.[]操作符重载方式插入数据
std::cout<<"---- part 1 ----"<<std::endl;
ISMAP mymap;
mymap[1] = "abc";
mymap[3] = "bcd";
mymap[7] = "def";
ISMAP::iterator myiter = mymap.begin();
for(;myiter != mymap.end();++myiter)
{
std::cout<<myiter->first<<std::endl;
std::cout<<myiter->second<<std::endl;
}
///2.insert方式插入数据
std::cout<<"---- part 2 ----"<<std::endl;
mymap.insert(ISPAIR(5,"cde"));
myiter = mymap.begin();
for(;myiter != mymap.end();++myiter)
{
std::cout<<myiter->first<<std::endl;
std::cout<<myiter->second<<std::endl;
}
///3.find方式查询数据并修改当前元素value
std::cout<<"---- part 3 ----"<<std::endl;
myiter = mymap.find(3);
if(myiter != mymap.end())
{
std::cout<<myiter->first<<std::endl;
std::cout<<myiter->second<<std::endl;
myiter->second = "modify1";
}
///4.[]操作符重载方式查询数据并修改当前元素value
std::cout<<"---- part 4 ----"<<std::endl;
mymap[5] = "modify2";
///5.键值存在的元素无法insert插入
std::cout<<"---- part 5 ----"<<std::endl;
mymap.insert(ISPAIR(7,"modify3"));
myiter = mymap.begin();
for(;myiter != mymap.end();++myiter)
{
std::cout<<myiter->first<<std::endl;
std::cout<<myiter->second<<std::endl;
}
return 0;
}
---- part 1 ----
1
abc
3
bcd
7
def
---- part 2 ----
1
abc
3
bcd
5
cde
7
def
---- part 3 ----
3
bcd
---- part 4 ----
---- part 5 ----
1
abc
3
modify1
5
modify2
7
def
3.解析
1.面对关联式容器,应该使用其所提供的find函数来搜寻元素,会比使用STL算法find()更有效率。因为STL算法find()只是循规搜索。
2.insert函数
pair<iterator,bool> insert(const value_type& x){ return t.insert_unique(x); }
此式将工作直接转给底层机制RB-tree的insert_unique()去执行。成功,iterator指向被插入的那个元素;失败,指向插入失败点(键值重复)的旧元素。
3.operator[]函数
typedef Key key_type;
typedef pair<const Key,T> value_type;
T& operator[](const key_type& k)
{
return (*((insert(value_type(k,T()))).first)).second ;
}
(1)value_type(k,T())
//产生一个暂时对象
(2)insert(value_type(k,T()))
//将该元素插入到map里
(3)insert(value_type(k,T())).first
//insert(value_type(k,T()))
返回一个pair<iterator,bool>
其第一个元素是个迭代器,指向插入妥当的新元素。
(4)*(insert(value_type(k,T())).first)
//提领该迭代器
(5)*(insert(value_type(k,T())).first).second
//获取一个map元素,是一个由键值和实值组成的pair,取其第二元素。
(6)实值以by reference方式传递。
4.参考文献
本文内容摘录于《STL源码剖析》