【STL】从源码看map

map
与set相同,map同样是以红黑树RB_Tree为底层机制的关联式容器。map的每一个元素都拥有两个值,一个键值(key)和一个实值(value)。它的内部实现是用一个pair来保存这个两个值。所以,map的每一个元素又是一个pair。下面是STL源码中stl_pair.h对pair的定义。
template <class T1, class T2>
struct pair {
  typedef T1 first_type;
  typedef T2 second_type;
  T1 first;
  T2 second;
  pair() : first(T1()), second(T2()) {}
  pair(const T1& a, const T2& b) : first(a), second(b) {}
#ifdef __STL_MEMBER_TEMPLATES
  template <class U1, class U2>
  pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
#endif
};
因为map底层是一棵红黑树(RB_Tree),红黑树的又是一种平衡二叉搜索树,自动排序效果很好。因此map内所有的元素都会根据元素的键值(key)自动排序。这一点也限制了我们不能修改map内元素的键值(key),键值(key)关系到map元素的排列规则,任意改变map的元素键值将会严重破坏map组织结构。那么STL源码是如何限制我们呢?
打开stl_map.h,你会看到这么一句话:
 typedef pair<const Key, T> value_type;
它将pair重命名成value_type,同时将pair的key声明成了const类型,限制我们不能对它做出修改。

map的底层是红黑树,map的各种操作接口红黑树也都提供了,所以几乎所有的map操作行为,都是调用红黑树RB_Tree的操作行为。下面我将从源码角度讲,map是如何调用红黑树的。


类型:“是你的又怎么样,我改个名字就是我的了”
请允许我用“不要脸”和“暴力”这两个名字来形容map在这里的做法,尽管它的整个实现都很“不要脸”。它先把红黑树重命名。再用重命名的红黑树把红黑树内的参数类型再次重命名。好像这样就变成自己的了,但的确是这样。
这里,我们可以明显感觉到STL库的 代码复用性是多么的高,它的编写者是多么的厉害。

源码:
private:
  //将红黑树重命名
  typedef rb_tree<key_type, value_type,
                  select1st<value_type>, key_compare, Alloc> rep_type;
  rep_type t;  // red-black tree representing map
public:
  //再对类型重命名
  typedef typename rep_type::pointer pointer;
  typedef typename rep_type::const_pointer const_pointer;
  typedef typename rep_type::reference reference;
  typedef typename rep_type::const_reference const_reference;
  typedef typename rep_type::iterator iterator;
  typedef typename rep_type::const_iterator const_iterator;
  typedef typename rep_type::reverse_iterator reverse_iterator;
  typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
  typedef typename rep_type::size_type size_type;
  typedef typename rep_type::difference_type difference_type;

当然,它也可以有一些自己的东西。

源码:
  typedef Key key_type;
  typedef T data_type;
  typedef T mapped_type;
  typedef pair<const Key, T> value_type;
  typedef Compare key_compare;
对象成员

map的源码里面对私有成员(private)的定义有以下四行:
private:
  typedef rb_tree<key_type, value_type,select1st<value_type>, key_compare, Alloc> rep_type;
  rep_type t;  // red-black tree representing map
我们可以看到,它直接将一个红黑树类型rb_tree(它的模板参数不再讲,想了解的可以去看看rb_tree的源码)重命名成rep_ type,并且利用rep_ type构建了一个红黑树对象t。如果你接着往下看,你会发现,map的所有方法中都有t的身影。

方法

基本方法
这里我将构造,赋值运算符重载定义为基本方法。(纯属本人为了方便)
构造
打开c++Reference,会看到map的构造有三种实现。前两种是构造函数,第三种是拷贝构造函数。但是它远远没有表面上这么简单。

1.(构造)
explicit map(const Compare& comp = Compare(),const Allocator& =
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值