C++函数对象
C++函数对象是重载了operator()的对象,可像函数一样调用,支持保存状态,常用于STL算法和回调函数中,比函数指针更灵活。
C++函数对象
函数对象
函数对象(仿函数)(Function Object,Functors)
函数对象其实就是重载了
operator()
的类或结构体的实例。它表现得像函数一样,可以用
()
括号调用,但本质是一个对象,可以有成员变量和状态。优点是它可以存储状态,比如调用时用到的参数、计数器、配置等。
函数对象既可以无状态(Multiply)也可以带状态(Counter),并且都能像函数一样调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
// 无状态函数对象:执行乘法
struct Multiply {
int operator()(int a, int b) const {
return a * b;
}
};
// 带状态的函数对象:计数调用次数
struct Counter {
int count = 0; // 内部状态
void operator()() {
++count;
std::cout << "Called " << count << " times" << std::endl;
}
};
int main() {
// 使用无状态函数对象
Multiply multiply;
int result = multiply(3, 4); // 调用了 multiply.operator()(3, 4)
std::cout << "Multiply result: " << result << std::endl; // 输出 12
// 使用带状态的函数对象
Counter counter;
counter(); // 输出:Called 1 times
counter(); // 输出:Called 2 times
counter(); // 输出:Called 3 times
return 0;
}
伪函数(Function Pointer)
伪函数通常就是指函数指针(Function Pointer),是指向函数的指针变量。
它可以指向普通函数,调用时通过指针间接调用函数。
例子:
1
2
3
4
5
6
int add(int a, int b) {
return a + b;
}
int (*funcPtr)(int, int) = add; // 函数指针指向 add 函数
int result = funcPtr(2, 3); // 通过函数指针调用函数
有时候人们也称它为“伪函数”,意思是它是对函数的引用(指针),而不是一个真正的对象。
函数对象 vs 函数指针 vs lambda
特性 | 函数对象 | 函数指针 | lambda 表达式 |
---|---|---|---|
是否可调用 | ✅ | ✅ | ✅ |
是否可保存状态 | ✅(成员变量) | ❌ | ✅(捕获变量) |
类型 | 类类型 | 指针 | 匿名闭包类 |
可用于 STL 算法 | ✅ | ✅(但无状态) | ✅(常用于 sort) |
是否支持内联优化 | ✅(更可能被优化) | ❌(指针有间接性) | ✅ |
函数对象 vs std::function
1
2
3
4
5
6
7
8
9
10
11
12
#include <functional>
struct Multiply {
int operator()(int a, int b) const {
return a * b;
}
};
int main() {
function<int(int, int)> f = Multiply(); // 用 std::function 接收仿函数
cout << f(6, 7) << endl; // 输出 42
}
std::function
是一种类型擦除容器;- 它可以接收函数对象、函数指针、lambda;
- 函数对象可以与之很好地结合,统一成接口参数。
标准库中的函数对象
C++ STL 提供了一些常用函数对象:
1
2
3
4
5
#include <functional>
greater<int>()(3, 2); // 返回 true,相当于 3 > 2
less<int>()(3, 2); // 返回 false,相当于 3 < 2
equal_to<int>()(3, 3); // 返回 true
这些定义在 <functional>
中,常用于模板泛型编程。
函数对象的实际应用场景
- 配合
sort
、for_each
、transform
等算法 - 封装可调用逻辑,提供函数接口但拥有对象状态
- 实现策略模式、回调机制
- 在 STL 容器中按需定制行为(如
priority_queue
)
本文由作者按照 CC BY 4.0 进行授权