STL中的仿函数

仿函数(functors)在C++标准中采用的名称是函数对象(function objects)。仿函数主要用于STL中的算法中,虽然函数指针虽然也可以作为算法的参数,但是函数指针不能满足STL对抽象性的要求,也不能满足软件积木的要求--函数指针无法和STL其他组件搭配,产生更灵活变化。

仿函数本质就是类重载了一个operator(),创建一个行为类似函数的对象。例如下面就是一个仿函数的例

struct plus{
    int operator()(const int& x, const int& y) const { return x + y; }
};
然后就可以如下这样使用

int a=1, b=2;
cout<<plus(a,b);
这样其实创建了一个临时无名的对象,之后调用其重载函数()。
但是STL中的仿函数不是这个样子的,为了使仿函数拥有被函数配接其(function adapter)修饰,彼此像积木一样地串接。仿函数应该定义自己相应的类别(associative types)。就像迭代器一样,为了融入STL,必须定义自己的5个相应类别。这样做的目的是为了让配接器能够取出,获得反函数的某些信息。相应类别都是一下typedef定义的预处理,在编译时就完成了替代,对程序执行效率没有影响,也不带来任何额外的负担。

仿函数相应的类别主要用来表现函数参数类型和返回值类型。在<stl_function.h>定义了两个struct,分别代表一元仿函数和二元仿函数。

// C++ Standard 规定,每一個 Adaptable Unary Function 都必须继承此类别
template <class Arg, class Result>
struct unary_function {
    typedef Arg argument_type;
    typedef Result result_type;
};

// C++ Standard 規定,每一個 Adaptable 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;
};

仿函数按照运算来分类,有以下3类:
1)算术类仿函数
    加:plus<T>
    减:minus<T>
    乘:multiplies<T>
    除:divides<T>
    模取:modulus<T>
    否定:negate<T>
2)关系运算类仿函数
    等于:equal_to<T>
    不等于:not_equal_to<T>
    大于:greater<T>
    大于等于:greater_equal<T>
    小于:less<T>
    小于等于:less_equal<T>
3)逻辑运算仿函数
    逻辑与:logical_and<T>
    逻辑或:logical_or<T>
    逻辑否:logical_no<T>

### C++ STL 仿函数的概念 在C++标准模板库(STL)中,仿函数(Functor),也被称为函数对象(function object)[^1]。这类对象的行为类似于函数,可以被调用并携带状态信息。 仿函数本质上是一个重载了`operator()`运算符的类实例。这意味着可以通过像调用普通函数一样来调用该类型的对象,并且可以在不改变接口的情况下维护内部状态或实现更复杂的逻辑。 ### 创建与使用仿函数的方法 为了创建一个仿函数,需定义一个新的类并在其中重写`operator()`成员函数。下面展示了一个简单的例子: ```cpp struct MultiplyBy { int factor; // 构造器初始化factor值 explicit MultiplyBy(int f): factor(f){} // 定义operator()使得此结构体可作为函数调用 int operator()(int value)const{ return value * factor; } }; ``` 这段代码实现了乘法操作的功能封装,在构造时指定乘数(factor),之后每次调用都返回输入参数value乘以此固定倍率的结果。 ### 实际应用场景下的仿函数应用案例 #### 自定义排序规则 当需要对容器内的元素按照特殊条件排序时,就可以利用仿函数来自定义比较方式。比如按降序排列整型向量: ```cpp #include <algorithm> #include <iostream> #include <vector> // 定义仿函数用于两个整数之间的大小关系判断(此处为大于) struct Greater { bool operator()(int a, int b) const { return a > b; } }; int main(){ std::vector<int> vec = {1, 5, 3, 2, 4}; std::sort(vec.begin(), vec.end(), Greater()); for (auto v : vec){ std::cout << v << " "; } return 0; } ``` 上述程序会输出 `5 4 3 2 1`, 表明已经成功地按照从大到小顺序进行了排序。 #### 配合STL算法迭代处理集合项 除了参与排序外,仿函数还经常与其他STL通用算法配合工作,如遍历整个序列并对每个元素施加相同的操作。例如,计算一系列数值总和或者统计满足某些属性的对象数量等场景下都非常有用。 ```cpp #include <numeric> #include <iostream> #include <vector> class SumWithOffset { public: SumWithOffset(double offset_) : sum_(0), offset(offset_){} void operator()(double val){ sum_ += val + offset; } double getSum()const{return sum_;} private: double sum_; double offset; }; int main(){ std::vector<double> numbers{1., 2., 3., 4.}; SumWithOffset summer(1.); std::for_each(numbers.begin(),numbers.end(),summer); std::cout<<"Total:"<<summer.getSum()<<'\n'; return 0; } ``` 这里演示的是累加带有偏移量offset的一组浮点数的过程。通过自定义的仿函数Summer完成这一任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值