前言
最近正好刚刚看完,《stl源码剖析》这本书的map和set的源码部分。但是看完之后又突然发现,之前怎么没有注意到map和set容器中key不能修改是怎么实现的。故,特此整理如下。
set容器中的实现
set中具体怎么实现的,看源码是最清楚的,下面就是set的部分源码:
1 class set 2 { 3 ...... 4 private: 5 typedef rb_tree<key_type, value_type, 6 identity<value_type>, key_compare, Alloc> rep_type; 7 rep_type t; // red-black tree representing set 8 public: 9 typedef typename rep_type::const_pointer pointer; 10 typedef typename rep_type::const_pointer const_pointer; 11 typedef typename rep_type::const_reference reference; 12 typedef typename rep_type::const_reference const_reference; 13 typedef typename rep_type::const_iterator iterator; // iterator定义为红黑树的const_iterator 14 typedef typename rep_type::const_iterator const_iterator; 15 typedef typename rep_type::const_reverse_iterator reverse_iterator; 16 typedef typename rep_type::const_reverse_iterator const_reverse_iterator; 17 typedef typename rep_type::size_type size_type; 18 typedef typename rep_type::difference_type difference_type; 19 ...... 20 }
map容器中的实现
同样,也是先看看map中有关的源码,然后结合源码分析,部分源码如下:
1 class map { 2 public: 3 4 ...... 5 // typedefs: 6 7 typedef Key key_type; 8 typedef T data_type; 9 typedef T mapped_type; 10 typedef pair<const Key, T> value_type; //value_type的定义 11 12 13 typedef Compare key_compare; 14 15 private: 16 typedef rb_tree<key_type, value_type, 17 select1st<value_type>, key_compare, Alloc> rep_type; // rb_tree的定义 18 19 rep_type t; // red-black tree representing map 20 public: 21 typedef typename rep_type::pointer pointer; 22 typedef typename rep_type::const_pointer const_pointer; 23 typedef typename rep_type::reference reference; 24 typedef typename rep_type::const_reference 25 typedef typename rep_type::iterator iterator; // iterator的定义 26 27 typedef typename rep_type::const_iterator const_iterator; 28 typedef typename rep_type::reverse_iterator reverse_iterator; 29 typedef typename rep_type::const_reverse_iterator const_reverse_iterator; 30 typedef typename rep_type::size_type size_type; 31 typedef typename rep_type::difference_type difference_type; 32 ...... 33 }
虽然map中的key值也是不能修改的,但是其中实值是可以修改的,所以map的迭代器不能是const_iterator,由上面的源码也可以看出。那么key值不允许修改是怎么实现的?map底层实现是通过红黑树实现的,其中红黑树的定义为
1 typedef rb_tree<key_type, value_type, 2 select1st<value_type>, key_compare, Alloc> rep_type; // rb_tree的定义
可以看到其中红黑树存储值的类型是value_type,而value_type定义是:
1 typedef pair<const Key, T> value_type; //value_type的定义
对于一个map容器,每次插入、删除或者查找返回的迭代器,其指向的红黑树中node节点,对其iterator->,解出的值的类型是value_type,这是一个pair的包装类,这个,我们定义了它的Key为const Key,而其值的类型为T,这样对于每次返回的迭代器,我们就可以实现,其中Key为const类型不能修改,对于实值不是const,可以修改。
这样就实现了对其的key的限制和实值的开放修改。