目录
定义
仿函数(Functor)是一种重载了 operator() 运算符的类或结构体。由于它重载了 operator() 运算符,所以它的实例可以像函数一样被调用
由于仿函数是一个类,所以它可以包含成员变量来存储状态,并且可以定义多个重载版本的 operator() 来支持不同数量和类型的参数。这使得仿函数比普通函数更加灵活
struct Add {
int operator()(int x, int y) const { return x + y; }
};
int main() {
Add add;
std::cout << add(1, 2) << std::endl; // 输出 3
return 0;
}
特点
仿函数可以包含状态。这意味着在同一时间里,由某个仿函数所代表的单一函数,可能有不同的状态。
仿函数可以重载 operator() 来支持不同数量和类型的参数。
由于仿函数通常被内联展开,所以它们通常比一般函数速度快。
即使两个仿函数定义相同,它们也可能属于不同的类型,因为它们可以是不同类的实例。
注意事项
由于仿函数是一个类,所以它需要被实例化才能使用。这意味着我们需要创建一个仿函数对象,并通过它来调用 operator()。
由于仿函数可以包含状态,所以我们需要注意在使用它之前是否需要初始化状态。
在将仿函数作为参数传递给其他函数或算法时,我们需要注意传递的是仿函数对象本身还是它的引用或指针。
如何理解仿函数的状态
1、Counter 类包含一个名为 count 的成员变量来存储状态。构造函数接受一个可选的初始值,并将其赋给 count。重载的 operator() 函数返回当前的 count 值,并将其递增。
class Counter {
public:
Counter(int start = 0) : count(start) {}
int operator()() { return count++; }
private:
int count;
};
int main() {
Counter c;
std::cout << c() << std::endl; // 输出 0
std::cout << c() << std::endl; // 输出 1
return 0;
}
2、在上面的例子中,不同的状态是由不同的初始值产生的,但这并不是唯一的方式。状态可以在仿函数的生命周期内通过多种方式改变。例如,我们可以通过成员函数来修改状态,或者在调用 operator() 时根据传入的参数来更新状态。
class Accumulator {
public:
Accumulator(int start = 0) : sum(start) {}
int operator()(int x) { sum += x; return sum; }
void reset(int start = 0) { sum = start; }
private:
int sum;
};
int main() {
Accumulator acc(10);
std::cout << acc(5) << std::endl; // 输出 15
std::cout << acc(10) << std::endl; // 输出 25
acc.reset();
std::cout << acc(5) << std::endl; // 输出 5
return 0;
}