什么是仿函数?
仿函数是重载了函数调用操作符 () 的类或结构体。它让对象可以像函数一样被调用,同时还能保存状态。
基本语法和实现
cpp
#include <iostream>
using namespace std;
// 最简单的仿函数
class Add {
public:
// 重载函数调用操作符
int operator()(int a, int b) {
return a + b;
}
};
// 带状态的仿函数
class Multiplier {
private:
int factor;
public:
Multiplier(int f) : factor(f) {} // 构造函数设置倍数
int operator()(int x) {
return x * factor;
}
};
int main() {
Add add;
cout << add(5, 3) << endl; // 输出: 8
Multiplier doubleIt(2);
Multiplier tripleIt(3);
cout << doubleIt(10) << endl; // 输出: 20
cout << tripleIt(10) << endl; // 输出: 30
return 0;
}
仿函数的核心优势
1. 状态保持能力
cpp
class Counter {
private:
int count;
string name;
public:
Counter(string n = "counter") : count(0), name(n) {}
int operator()() {
cout << name << ": " << count << endl;
return count++;
}
void reset() { count = 0; }
int getCount() const { return count; }
};
int main() {
Counter c1("主要计数器");
Counter c2("备用计数器");
c1(); // 主要计数器: 0
c1(); // 主要计数器: 1
c2(); // 备用计数器: 0
c1(); // 主要计数器: 2
return 0;
}
2. 模板编程中的威力
cpp
#include <vector>
#include <algorithm>
// 通用的转换器仿函数
template<typename T>
class Transformer {
private:
T offset;
public:
Transformer(T o) : offset(o) {}
T operator()(T x) const {
return x + offset;
}
};
// 使用仿函数的通用算法
template<typename Iterator, typename Func>
void transformRange(Iterator begin, Iterator end, Func func) {
for (auto it = begin; it != end; ++it) {
*it = func(*it);
}
}
int main() {
vector<int> numbers = {1, 2, 3, 4, 5};
vector<double> decimals = {1.1, 2.2, 3.3, 4.4};
Transformer<int> add5(5);
Transformer<double> add2_5(2.5);
transformRange(numbers.begin(), numbers.end(), add5);
transformRange(decimals.begin(), decimals.end(), add2_5);
for (auto num : numbers) cout << num << " "; // 6 7 8 9 10
cout << endl;
for (auto num : decimals) cout << num << " "; // 3.6 4.7 5.8 6.9
cout << endl;
return 0;
}
STL中的仿函数体系
内置仿函数分类
cpp
#include <functional>
#include <algorithm>
#include <vector>
void demonstrateSTLFunctors() {
vector<int> nums = {1, 2, 3, 4, 5};
// 算术仿函数
plus<int> add;
minus<int> subtract;
multiplies<int> multiply;
divides<int> divide;
modulus<int> mod;
negate<int> negate;
cout << "算术运算:" << endl;
cout << "10 + 5 = " << add(10, 5) << endl; // 15
cout << "10 * 5 = " << multiply(10, 5) << endl; // 50
cout << "-10 = " << negate(10) << endl; // -10
// 关系仿函数
greater<int> gt;
less<int> lt;
equal_to<int> eq;
cout << "\n关系运算:" << endl;
cout << "10 > 5: " << gt(10, 5) << endl; // 1 (true)
cout << "10 == 5: " << eq(10, 5) << endl; // 0 (false)
// 逻辑仿函数
logical_and<bool> land;
logical_or<bool> lor;
logical_not<bool> lnot;
cout << "\n逻辑运算:" << endl;
cout << "true && false: " << land(true, false) << endl; // 0
cout << "!true: " << lnot(true) << endl; // 0
}
在STL算法中的应用
cpp
#include <numeric>
#include <algorithm>
void stlAlgorithmsWithFunctors() {
vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 1. 排序 - 使用仿函数自定义排序规则
sort(nums.begin(), nums.end(), greater<int>());
// nums: 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
// 2. 累积计算 - 使用仿函数指定操作
int sum = accumulate(nums.begin(), nums.end(), 0, plus<int>());
int product = accumulate(nums.begin(), nums.end(), 1, multiplies<int>());
cout << "总和: " << sum << endl; // 55
cout << "乘积: " << product << endl; // 3628800
// 3. 变换操作
vector<int> result(nums.size());
transform(nums.begin(), nums.end(), result.begin(), negate<int>());
// result: -10, -9, -8, -7, -6, -5, -4, -3, -2, -1
}
高级仿函数技术
1. 仿函数适配器
cpp
#include <functional>
#include <algorithm>
void functorAdapters() {
vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 使用 bind2nd 绑定第二个参数(C++17 前)
// auto greater_than_5 = bind2nd(greater<int>(), 5);
// 现代C++使用 bind
using namespace std::placeholders;
auto greater_than_5 = bind(greater<int>(), _1, 5);
int count = count_if(nums.begin(), nums.end(), greater_than_5);
cout << "大于5的元素个数: " << count << endl; // 5
// 使用 not1 取反
auto not_greater_than_5 = bind(logical_not<bool>(),
bind(greater<int>(), _1, 5));
count = count_if(nums.begin(), nums.end(), not_greater_than_5);
cout << "不大于5的元素个数: " << count << endl; // 5
}
2. 仿函数组合
cpp
// 复杂的仿函数组合
class ComplexFilter {
private:
int min_val;
int max_val;
public:
ComplexFilter(int min, int max) : min_val(min), max_val(max) {}
bool operator()(int x) const {
return x >= min_val && x <= max_val && x % 2 == 0;
}
};
// 模板化的仿函数组合
template<typename F1, typename F2>
class AndComposition {
private:
F1 f1;
F2 f2;
public:
AndComposition(F1 func1, F2 func2) : f1(func1), f2(func2) {}
template<typename T>
bool operator()(const T& x) const {
return f1(x) && f2(x);
}
};
int main() {
vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 使用组合仿函数
ComplexFilter filter(3, 8);
int count = count_if(nums.begin(), nums.end(), filter);
cout << "3-8之间的偶数: " << count << endl; // 3 (4,6,8)
return 0;
}
实际应用案例
案例1:智能数据处理器
cpp
class DataProcessor {
private:
double scale_factor;
double offset;
int process_count;
public:
DataProcessor(double scale, double off)
: scale_factor(scale), offset(off), process_count(0) {}
double operator()(double input) {
process_count++;
double result = (input * scale_factor) + offset;
cout << "处理 #" << process_count << ": "
<< input << " -> " << result << endl;
return result;
}
void setParameters(double scale, double off) {
scale_factor = scale;
offset = off;
}
int getProcessCount() const { return process_count; }
void resetCount() { process_count = 0; }
};
int main() {
DataProcessor processor(2.5, 10.0);
vector<double> data = {1.0, 2.0, 3.0, 4.0};
transform(data.begin(), data.end(), data.begin(), processor);
// 输出:
// 处理 #1: 1 -> 12.5
// 处理 #2: 2 -> 15
// 处理 #3: 3 -> 17.5
// 处理 #4: 4 -> 20
cout << "总处理次数: " << processor.getProcessCount() << endl; // 4
return 0;
}
案例2:策略模式仿函数
cpp
// 排序策略仿函数
class AscendingSort {
public:
template<typename T>
bool operator()(const T& a, const T& b) const {
return a < b;
}
};
class DescendingSort {
public:
template<typename T>
bool operator()(const T& a, const T& b) const {
return a > b;
}
};
class AbsoluteValueSort {
public:
bool operator()(int a, int b) const {
return abs(a) < abs(b);
}
};
template<typename SortStrategy>
void sortWithStrategy(vector<int>& data, SortStrategy strategy) {
sort(data.begin(), data.end(), strategy);
}
int main() {
vector<int> numbers = {-5, 3, -1, 4, -2};
// 使用不同的排序策略
sortWithStrategy(numbers, AscendingSort());
// numbers: -5, -2, -1, 3, 4
sortWithStrategy(numbers, DescendingSort());
// numbers: 4, 3, -1, -2, -5
sortWithStrategy(numbers, AbsoluteValueSort());
// numbers: -1, -2, 3, 4, -5
return 0;
}
仿函数 vs Lambda表达式
cpp
void compareWithLambda() {
vector<int> nums = {1, 2, 3, 4, 5, 6};
// 仿函数方式
class IsEvenFunctor {
public:
bool operator()(int x) const { return x % 2 == 0; }
};
// Lambda方式(本质是匿名仿函数)
auto isEvenLambda = [](int x) { return x % 2 == 0; };
int count1 = count_if(nums.begin(), nums.end(), IsEvenFunctor());
int count2 = count_if(nums.begin(), nums.end(), isEvenLambda);
int count3 = count_if(nums.begin(), nums.end(),
[](int x) { return x % 2 == 0; }); // 直接使用
cout << "偶数个数: " << count1 << endl; // 3
cout << "偶数个数: " << count2 << endl; // 3
cout << "偶数个数: " << count3 << endl; // 3
}
性能优势
仿函数的性能优势主要来自:
-
内联优化:编译器可以轻松内联仿函数的调用
-
避免函数指针:模板实例化时类型信息完整
-
静态多态:编译期决议,无运行时开销
cpp
// 仿函数 - 可以被内联
class SquareFunctor {
public:
int operator()(int x) const { return x * x; }
};
// 函数指针 - 较难内联
int squareFunction(int x) { return x * x; }
template<typename Func>
void benchmark(const string& name, Func func) {
auto start = chrono::high_resolution_clock::now();
int result = 0;
for (int i = 0; i < 1000000; ++i) {
result += func(i);
}
auto end = chrono::high_resolution_clock::now();
auto duration = chrono::duration_cast<chrono::microseconds>(end - start);
cout << name << " 耗时: " << duration.count() << " 微秒" << endl;
}
int main() {
benchmark("仿函数", SquareFunctor());
benchmark("函数指针", squareFunction);
benchmark("Lambda", [](int x) { return x * x; });
return 0;
}
总结
仿函数是C++泛型编程的基石,它们提供了:
-
✅ 状态保持:可以在调用之间保存信息
-
✅ 高性能:编译器可以很好地进行优化
-
✅ 灵活性:可以通过模板参数定制行为
-
✅ 类型安全:编译期类型检查
-
✅ 可组合性:可以创建复杂的操作组合
掌握仿函数对于理解STL设计理念和编写高效的C++代码至关重要!