03月30, 2014

关于C++ STL中 max、greater函数的实现

注意:这是一篇从旧博客恢复的文章。

原地址:http://freemeepo.com/blog/archives/95

注:有更新


(只讨论在G++中的实现情况)

在G++中,max是用函数实现的。头文件中定义如下:

  template<typename _Tp>
    inline const _Tp&
    max(const _Tp& __a, const _Tp& __b)
    {
      // concept requirements
      __glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
      //return  __a < __b ? __b : __a;
      if (__a < __b)
    return __b;
      return __a;
    }

而没有使用宏的方式(类似于#define max(a,b) (((a) < (b)) ? (b) : (a))这样的定义)。

UPDATE: 事实上,使用宏来定义max是非常危险的。

它使用的是template,这样实现了不管什么类型都可以执行这个函数。不过需要注意的是,template用于普通函数可以直接这样做,但用于类时,在使用时则需加尖括号显式声明类型,例如vector<int> v;

而greater函数的实现,则不太一样了。

先说一下greater函数的用法。例如我们在sort的时候,这样使用sort(v.begin(),v.end(),greater<int>());则可以对int型的vector进行降序排序。经过思考后发现,这样函数的用法跟其他函数好像不大一样,比如为什么在最后要加个括号呢?

其实,这个函数并非真正的函数,而是叫做仿函数的一个东西,它是用一个类实现的,并在其中重载了括号运算符,使它用起来像个函数而已。G++中是这样实现的:

  template<typename _Tp>
    struct greater : public binary_function<_Tp, _Tp, bool>
    {
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x > __y; }
    };

于是我们可以这样调用这个函数greater<int>()(3,5),结果为0。这样还有两个问题:

1、为何要用尖括号指定类型?

这是因为template对类使用必须指定类型。

2、传参前为何需要加一对空括号呢?

这是因为它其实是调用了一个默认构造函数。因为它的本质还是一个类型,需要构造一个变量是这个类型,然后调用这个变量的()运算符。用加括号的方法就相当于构造了一个变量,这种方法与vector<int>()point(3,5)其实本质上是一样的,只是一个是调用默认构造函数,一个是带两个参数的构造函数。

其实greater这样使用也是可以的:

    vector<int> v;
    /*------*/
    greater<int> g;
    sort(v.begin(),v.end(),g);

另外,要想用仿函数作为某个函数的参数传入的话,就必须用template,因为仿函数确实不是函数,在参数定义上很麻烦,所以template很好地解决了这个问题。

本文链接:https://debug.fanzheng.org/post/implementation-of-max-and-greater-in-CPP-STL.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。