STL源码之仿函数

本文深入探讨STL中的仿函数,包括一元和二元仿函数,算术、关系和逻辑运算类,以及正同、选择和投射的概念。仿函数通过对象重载操作符实现函数行为,具有灵活性和可配接性,优于函数指针,为STL带来强大功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本节将分析STL六部分之一的仿函数, 在前面分析容器以及算法的时候都有使用过仿函数, 在算法中我们还自定义过仿函数(函数对象), 就是使用struct或者class重载运算符, 就是行为类似于函数的对象.

  • 根据仿函数的操作数可分为 : 一元和二元仿函数.

  • 根据功能可分为 : 算术运算, 关系运算, 逻辑运算.

仿函数与函数指针

STL采用对象重载操作实现函数行为并没有直接定义函数指针来代替仿函数, 主要有几点原因让STL选择仿函数

  1. 函数指针不能满足STL的抽象性
  2. 函数指针不能与STL的其他组件搭配, 不够灵活
  3. 仿函数具有可配接性, 可以满足traits编程, 也是能在编译期间就能完成, 不会有运行时的开销

仿函数分析

一元仿函数

一元仿函数基类(unary_function)

template <class Arg, class Result>
struct unary_function {
    typedef Arg argument_type;	// 参数类型别名
    typedef Result result_type;	// 返回值类型别名
};
二元仿函数

二元仿函数基类(binary_function)

template <class Arg1, class Arg2, class Result>
struct binary_function {
    typedef Arg1 first_argument_type;	// 参数类型别名
    typedef Arg2 second_argument_type;	// 参数类型别名
    typedef Result result_type;	// 返回值类型别名
}; 
算术运算

每个仿函数都继承了二元仿函数, 仿函数可以通过继承使STL更灵活, 函数指针无法这样灵活的操作

  • 加法

    template <class T>
    struct plus : public binary_function<T, T, T> {
        T operator()(const T& x, const T& y) const { return x + y; }
    };
    
  • 乘法

    template <class T>
    struct multiplies : public binary_function<T, T, T> {
        T operator()(const T& x, const T& y) const { return x * y; }
    };
    
  • 除法

    template <class T>
    struct divides : public binary_function<T, T, T> {
        T operator()(const T& x, const T& y) const { return x / y; }
    };
    
  • 减法

    template <class T>
    struct minus : public binary_function<T, T, T> {
    	T operator()(const T& x, const T& y) const { return x - y; }
    };
    
  • 取模

    template <class T>
    struct modulus : public binary_function<T, T, T> {
        T operator()(const T& x, const T& y) const { return x % y; }
    };
    
  • 相反

    // 继承的是一元仿函数
    template <class T>
    struct negate : public unary_function<T, T> {
        T operator()(const T& x) const { return -x; }
    };
    

正同元素

正同元素 : 数值A与该元素做op得到的依然还是A.

template <class T> inline T identity_element(plus<T>) { return T(0); }
// 在stl_numeric.h的power中有使用
template <class T> inline T identity_element(multiplies<T>) { return T(1); }
关系运算类
  • 等于

    template <class T>
    struct equal_to : public binary_function<T, T, bool> {
        bool operator()(const T& x, const T& y) const { return x == y; }
    };
    
  • 不等于

    template <class T>
    struct not_equal_to : public binary_function<T, T, bool> {
        bool operator()(const T& x, const T& y) const { return x != y; }
    };
    
  • 大于

    template <class T>
    struct greater : public binary_function<T, T, bool> {
        bool operator()(const T& x, const T& y) const { return x > y; }
    };
    
  • 小于

    template <class T>
    struct less : public binary_function<T, T, bool> {
        bool operator()(const T& x, const T& y) const { return x < y; }
    };
    

逻辑运算类
  • template <class T>
    struct logical_or : public binary_function<T, T, bool> {
        bool operator()(const T& x, const T& y) const { return x || y; }
    };
    
  • template <class T>
    struct logical_and : public binary_function<T, T, bool> {
        bool operator()(const T& x, const T& y) const { return x && y; }
    };
    
  • template <class T>
    struct logical_not : public unary_function<T, bool> {
        bool operator()(const T& x) const { return !x; }
    };
    
正同,选择,投射

正同 : 任何数值调用该函数都不会有改变

选择 : 接受一个pair类型, 并且返回第一个元素或者第二个元素

投影 : 接受一个pair类型, 忽略第二个元素返回第一个元素或者忽略第一个元素返回第二个元素

  • 正同

    template <class T>
    struct identity : public unary_function<T, T> {
      const T& operator()(const T& x) const { return x; }
    };
    
  • 选择

    // 选择第一个元素
    template <class Pair>
    struct select1st : public unary_function<Pair, typename Pair::first_type> {
      const typename Pair::first_type& operator()(const Pair& x) const
      {
        return x.first;
      }
    };
    // 选择第二个元素
    template <class Pair>
    struct select2nd : public unary_function<Pair, typename Pair::second_type> {
      const typename Pair::second_type& operator()(const Pair& x) const
      {
        return x.second;
      }
    };
    
  • 投影

    // 忽略第二个元素返回第一个元素
    template <class Arg1, class Arg2>
    struct project1st : public binary_function<Arg1, Arg2, Arg1> {
      Arg1 operator()(const Arg1& x, const Arg2&) const { return x; }
    };
    // 忽略第一个元素返回第二个元素
    template <class Arg1, class Arg2>
    struct project2nd : public binary_function<Arg1, Arg2, Arg2> {
      Arg2 operator()(const Arg1&, const Arg2& y) const { return y; }
    };
    

总结

仿函数使STL变得非常的灵活, 用户也可以自定义, 并且提供接口关联配接器, 下一节我们就分析STL最后的组件–配接器.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值