C++:默认参数,模板,map源码分析

本文详细介绍了STL中的map容器,它是一个由键值对组成的关联容器,通过键来访问值,且键是严格弱排序的。文章通过示例展示了如何创建和使用map,包括默认构造函数和带比较函数的对象构造。此外,还讨论了如何自定义比较函数以实现升序或降序的map,并给出了实际的代码实现。
摘要由CSDN通过智能技术生成

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

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值