函数对象是重载了operator()的类实例,可像函数一样调用并携带状态。例如GreaterThan类通过成员变量threshold保存阈值,在std::count_if中统计大于指定值的元素个数,相比函数指针能内联优化且支持状态存储,比普通函数更灵活高效。C++11的lambda表达式本质也是匿名函数对象,适用于简洁场景,而复杂逻辑推荐自定义函数对象以提升代码可读性与复用性。

在C++中,函数对象(Functor)是指可以像函数一样被调用的对象。它不是普通的函数指针,而是一个类或结构体的实例,该类重载了函数调用运算符 operator()。因此,函数对象既可以拥有状态,又能像函数一样使用,是STL算法中常用的重要机制。
什么是函数对象(Functor)?
函数对象本质上是一个定义了 operator() 的类对象。当一个对象重载了这个运算符后,就可以像调用函数一样使用它,例如:
obj(args)
这种机制让对象具备“可调用”的特性,同时还能封装数据和行为,比普通函数更灵活。
立即学习“C++免费学习笔记(深入)”;
函数对象的优势
- 可携带状态:与普通函数或函数指针不同,函数对象可以包含成员变量,保存调用之间的状态。
- 性能更高:编译器通常能内联 operator() 调用,提升执行效率。
- 泛型编程友好:在STL算法中广泛使用,如 std::sort、std::for_each 等都支持传入函数对象。
自定义函数对象示例
下面是一个简单的函数对象,用于判断一个整数是否大于给定值:
#include#include #include struct GreaterThan { int threshold; // 构造函数初始化阈值 GreaterThan(int val) : threshold(val) {} // 重载 operator() bool operator()(int x) const { return x > threshold; } }; int main() { std::vector nums = {1, 3, 5, 7, 9, 2, 4, 6, 8}; // 使用函数对象统计大于5的元素个数 int count = std::count_if(nums.begin(), nums.end(), GreaterThan(5)); std::cout << "大于5的元素有:" << count << " 个\n"; return 0; }
输出结果为:
大于5的元素有:4 个
在这个例子中,GreaterThan 是一个函数对象类,构造时接收一个阈值,每次调用时判断传入值是否更大。由于它是对象,可以灵活设置不同的阈值。
函数对象与lambda表达式的比较
C++11引入了lambda表达式,也可以实现类似功能:
int threshold = 5;
auto isGreater = [threshold](int x) { return x > threshold; };
int count = std::count_if(nums.begin(), nums.end(), isGreater);
lambda本质上会被编译器转换为一个匿名的函数对象。对于简单逻辑,lambda更简洁;对于复杂逻辑或需要复用的情况,自定义函数对象更清晰。
基本上就这些。函数对象是C++中实现“可调用对象”的基础方式之一,理解它有助于深入掌握STL和泛型编程的设计思想。不复杂但容易忽略的是它的状态保持能力——这是普通函数难以做到的。











