map是STL的一个标准关联容器,其element为键值对(pair<key,value>);
主要通过key进行访问value,而map的key 是strict weaking ordering 的 ;
在学习map时想要构建一个从小到大排序的map,如下:
1.默认参数--恰如其名
#include<iostream> int func(int a,int b,int c=3) { std:: cout<<a<<"<<"<<b<<"<<"<<c<<std::endl; } int main(void) { func(1,2); func(5,6,7); return 0; }
1<<2<<3 5<<6<<7
2.模板--代码重用
#include<iostream> using namespace std; //函数模板 template<class T,typename U> T& func(T key,U value) { cout<<key<<"<<"<<value<<endl; } template<class T,typename U> U& fun2(T key,U value) { cout<<key<<"<<"<<value<<endl; } //类模板 template<class T,typename U> class ACC{ public: T ax; U bx; ACC(T a,U b) { ax=a; bx=b; cout<<ax<<"<<"<<bx<<endl; } }; int main(void) { func("hello",8); fun2(1.532,'H'); ACC<int,float> a(5,10.4L); return 0; }
hello<<8 1.532<<H 5<<10.4
大多情况下 typename 和class是等价的, 统一只用class/typename可能更好一点
3. STL map 源码分析
在一个map对象上选择 go to definition 可以以转到源码:stl_map.h
描述:
/** * @brief A standard container made up of (key,value) pairs, which can be * retrieved based on a key, in logarithmic time. * * @ingroup associative_containers * * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. * @tparam _Compare Comparison function object type, defaults to less<_Key>. * @tparam _Alloc Allocator type, defaults to * allocator<pair<const _Key, _Tp>. * * Meets the requirements of a <a href="tables.html#65">container</a>, a * <a href="tables.html#66">reversible container</a>, and an * <a href="tables.html#69">associative container</a> (using unique keys). * For a @c map<Key,T> the key_type is Key, the mapped_type is T, and the * value_type is std::pair<const Key,T>. * * Maps support bidirectional iterators. * * The private tree data is declared exactly the same way for map and * multimap; the distinction is made entirely in how the tree functions are * called (*_unique versus *_equal, same as the standard).
template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>, typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > > class map { public: typedef _Key key_type; typedef _Tp mapped_type; typedef std::pair<const _Key, _Tp> value_type; typedef _Compare key_compare; typedef _Alloc allocator_type; ... }
从描述可以看到map类模板上有4个模板参数:_Key,_Tp,_Compare,_Alloc;
其中_Compare 与_Alloc已经有了默认参数了;
constructor
// [23.3.1.1] construct/copy/destroy // (get_allocator() is also listed in this section) /** * @brief Default constructor creates no elements. */ map() : _M_t() { } /** * @brief Creates a %map with no elements. * @param __comp A comparison object. * @param __a An allocator object. */ explicit map(const _Compare& __comp, const allocator_type& __a = allocator_type()) : _M_t(__comp, _Pair_alloc_type(__a)) { } /** * @brief %Map copy constructor. * @param __x A %map of identical element and allocator types. * * The newly-created %map uses a copy of the allocation object * used by @a __x. */ map(const map& __x) : _M_t(__x._M_t) { }
就第一个构造函数
map()
: _M_t() { }
默认构造函数,_M_t是什么? 继续寻找得到:
private: /// This turns a red-black tree into a [multi]map. typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<value_type>::other _Pair_alloc_type; typedef _Rb_tree<key_type, value_type, _Select1st<value_type>, key_compare, _Pair_alloc_type> _Rep_type; /// The actual tree structure. _Rep_type _M_t;
_M_T其实是一个红黑树的结构,而且是 map的私有变量,即map默认构造函数构造了一个红黑树的数据结构,冒号":"使用link=https://blog.csdn.net/zimingjushi/article/details/6549390
第二个构造函数:
/** * @brief Creates a %map with no elements. * @param __comp A comparison object. * @param __a An allocator object. */ explicit map(const _Compare& __comp, const allocator_type& __a = allocator_type()) : _M_t(__comp, _Pair_alloc_type(__a)) { }
map有了两个默认参数为_comp和_a;
_comp 是_Compare l类型即,typename _Compare = std::less<_Key>
正是这个std::less<_key>决定了严格弱排序
template<typename _Tp> struct less : public binary_function<_Tp, _Tp, bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; } };
可以看到std::less<_Key>是个模板/泛型 结构体,并实现了()操作符,并可以如下使用:
std::less<int> _less; assert(_less(1,2)==true);
自定义map ordering
template<typename T> struct GREATER { bool operator()(const T& __x, const T& __y)const{ return __x > __y; } };
template <typename T> void print_map_info (T &map) { printf("map::size=%ld, max_size=%ld, address=%p\n",map.size(),map.max_size(),&map); typename T::iterator it; for(it=map.begin();it!=map.end();it++) { printf("%p:",it); cout<<"<"<<it->first<<","<<it->second<<"> "; } cout<<endl; } template<typename T> struct GREATER { operator()(const T& __x, const T& __y)const{ return __x > __y; } }; //this is the default compare std::less<int> _less; assert(_less(1,2)==true); //this is my own compare GREATER<int>_greater; assert(_greater(1,2)==false); map<int,char,std::less<int> >mm; map<int,char,GREATER<int> >mm2; mm.insert(m.begin(),m.end()); mm2.insert(m.begin(),m.end()); print_map_info(mm); print_map_info(mm2);
map::size=5, max_size=1717986918, address=000000000070fd50 0000000000f41aa0:<0,A> 0000000000f41ad0:<2,C> 0000000000f41b00:<4,E> 0000000000f45ca0:<6,G> 0000000000f45cd0:<8,I> map::size=5, max_size=1717986918, address=000000000070fd80 0000000000f46110:<8,I> 0000000000f460e0:<6,G> 0000000000f45d60:<4,E> 0000000000f45d30:<2,C> 0000000000f45d00:<0,A>
如上所示,使用自定义的objecrt GREATE 代替了默认参数 std::less<_key>
结果得到了升序的map