一、仿函数(Functor)
(1)仿函数与其适用场景
仿函数(Functor,Function Object)是重载 operator()
的类或结构体对象,它的行为类似于函数,可以像普通函数一样被调用。
特点:
- 可以携带状态:仿函数可以存储数据,而普通函数无法做到这一点。
- 性能优化:在 STL 算法(如
sort
、for_each
)中,仿函数的执行比函数指针更快。 - 增强可读性:自定义运算逻辑,提高代码的灵活性。
适用场景:
- 排序 (
sort
、stable_sort
) - 变换 (
transform
、for_each
) - 查找 (
find_if
) - 过滤 (
remove_if
)
头文件:
#include <functional>
(2)普通函数 vs 仿函数
功能 | 普通函数 | 仿函数(Functor) |
---|---|---|
是否可以存储状态 | ❌ | ✅ |
性能 | 较慢 | 更快(内联优化) |
适用于 STL 算法 | ✅ | ✅ 更推荐 |
可读性 | 适中 | 更灵活 |
二、STL 算术仿函数
仿函数 | 作用 |
---|---|
plus<T> | 加 |
minus<T> | 减 |
multiplies<T> | 乘 |
divides<T> | 除 |
modulus<T> | 取模 |
negate<T> | 数值取反 |
示例1——使用 plus<int>
进行加法:
#include <iostream>
using namespace std;
#include <functional> // 引入 STL 仿函数
int main() {
plus<int> add; // 定义加法仿函数
cout << "10 + 20 = " << add(10, 20) << endl;
system("pause");
return 0;
}
示例2——transform
结合仿函数:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <functional>
int main() {
vector<int> v1 = {1, 2, 3, 4};
vector<int> v2 = {10, 20, 30, 40};
vector<int> result(4);
// 使用 plus<int> 计算 v1 + v2
transform(v1.begin(), v1.end(), v2.begin(), result.begin(), plus<int>());
for (int num : result)
{
cout << num << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:
transform
函数的作用是用于对容器或指定迭代器范围的每个元素进行指定的“转换操作”,并将“转换结果”存储到另一个容器中 ;transform
函数接受一个或两个输入范围 , 以及一个输出范围 ,并根据提供的一元函数对象或二元函数对象对“输入范围内的元素”进行转换 ;std::plus<int>()
让transform
自动执行加法运算。
三、STL 关系仿函数
仿函数 | 作用 |
---|---|
equal_to<T> | 等于 |
not_equal_to<T> | 不等于 |
greater<T> | 大于 |
less<T> | 小于 |
greater_equal<T> | 大于或等于 |
less_equal<T> | 小于或等于 |
示例——使用 greater<int>
进行降序排序:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <functional>
int main() {
vector<int> nums = { 5, 2, 8, 3, 1 };
// 使用 greater<int> 进行降序排序
sort(nums.begin(), nums.end(), greater<int>());
for (int num : nums)
{
cout << num << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:
greater<int>()
代替了operator()(int a, int b) { return a > b; }
。
四、STL 逻辑仿函数
仿函数 | 作用 |
---|---|
logical_and<T> | 逻辑与 |
logical_or<T> | 逻辑或 |
logical_not<T> | 逻辑非 |
示例——logical_not<bool>
取反:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <functional>
int main() {
vector<bool> v = { true, false, true, false };
vector<bool> result(4);
// 取反
transform(v.begin(), v.end(), result.begin(), logical_not<bool>());
for (bool b : result)
{
cout << boolalpha << b << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:
std::logical_not<bool>()
让transform
自动执行对容器v
中的元素取反,并保存到result
容器中。
五、STL 位运算仿函数
仿函数 | 作用 |
---|---|
bit_and<T> | 按位与 |
bit_or<T> | 按位或 |
bit_xor<T> | 按位异或 |
bit_not<T> | 按位取反 |
示例——计算所有元素的按位与:
#include <iostream>
using namespace std;
#include <vector>
#include <functional>
#include <numeric> // std::accumulate
#include <bitset>
int main() {
vector<int> nums = { 0b1111, 0b1010, 0b1100 }; // 二进制: {15, 10, 12}
// 使用 std::bit_and<> 计算所有元素的按位与
int result = accumulate(nums.begin(), nums.end(), ~0, bit_and<int>());
cout << "按位与结果: " << result << " (二进制: " << bitset<4>(result) << ")" << endl;
system("pause");
return 0;
}
注意:
accumulate
函数用来计算特定范围内(包括连续的部分和初始值)所有元素的和,除此之外,还可以用指定的二进制操作来计算特定范围内的元素结果。accumulate(nums.begin(), nums.end(), ~0, bit_and<int>());
中~0
为元素累计运算的初始值(即二进制数全1为初始值)。
六、自定义仿函数
示例——仿函数实现自定义排序:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
// 自定义仿函数(奇数优先排序)
class CustomSort
{
public:
bool operator()(int a, int b)
{
return (a % 2) > (b % 2); // 让奇数排前面
}
};
int main() {
vector<int> nums = { 3, 6, 1, 8, 5, 2 };
// 使用自定义仿函数
sort(nums.begin(), nums.end(), CustomSort());
for (int num : nums)
{
cout << num << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:
CustomSort()
让sort()
按照“奇数优先”排序!