当前位置: 首页 > news >正文

可调用对象(2)-仿函数

仿函数(Functors)

仿函数(Functors),又称函数对象(Function Objects),是在C++中重载了 operator() 的类或结构体实例。仿函数不仅可以像普通函数一样被调用,还能携带状态,提供更大的灵活性和功能性。

定义与使用

仿函数是通过定义一个类或结构体,并重载其调用运算符 operator() 来实现的。

#include <iostream>// 定义一个仿函数类
struct Adder {int to_add;// 构造函数Adder(int value) : to_add(value) {}// 重载()运算符int operator()(int x) const {return x + to_add;}
};int main() {Adder add5(5); // 创建一个添加5的仿函数std::cout << "10 + 5 = " << add5(10) << std::endl; // 输出: 10 + 5 = 15return 0;
}

特点

  1. 携带状态: 仿函数可以拥有内部状态,通过成员变量存储数据,使其在调用时具备上下文信息。
  2. 灵活性高: 可以根据需要添加更多的成员函数和变量,扩展功能。
  3. 性能优化: 编译器可以对仿函数进行优化,例如内联展开,提高执行效率。

高级示例

仿函数不仅可以执行简单的计算,还可以进行复杂的操作。例如,实现一个可变的仿函数,用于累加多个值。

#include <iostream>// 可变累加器仿函数
struct Accumulator {int sum;Accumulator() : sum(0) {}// 重载()运算符void operator()(int x) {sum += x;}
};int main() {Accumulator acc;acc(10);acc(20);acc(30);std::cout << "总和: " << acc.sum << std::endl; // 输出: 总和: 60return 0;
}

使用仿函数的标准库算法

许多标准库算法可以接受仿函数作为参数,使得算法的行为更加灵活和可定制。

#include <iostream>
#include <vector>
#include <algorithm>// 仿函数:判断一个数是否大于某个阈值
struct IsGreaterThan {int threshold;IsGreaterThan(int t) : threshold(t) {}bool operator()(int x) const {return x > threshold;}
};int main() {std::vector<int> numbers = {1, 5, 10, 15, 20};// 使用仿函数进行筛选IsGreaterThan greaterThan10(10);auto it = std::find_if(numbers.begin(), numbers.end(), greaterThan10);if(it != numbers.end()) {std::cout << "第一个大于10的数是: " << *it << std::endl; // 输出: 第一个大于10的数是: 15} else {std::cout << "没有找到大于10的数。" << std::endl;}return 0;
}

仿函数与模板

仿函数与模板相结合,可以实现高度通用和可复用的代码。例如,编写一个通用的比较仿函数。

#include <iostream>
#include <vector>
#include <algorithm>// 通用比较仿函数
template <typename T>
struct Compare {bool operator()(const T& a, const T& b) const {return a < b;}
};int main() {std::vector<int> numbers = {5, 2, 8, 1, 9};// 使用仿函数进行排序std::sort(numbers.begin(), numbers.end(), Compare<int>());std::cout << "排序后的数字: ";for(auto num : numbers) {std::cout << num << " "; // 输出: 1 2 5 8 9}std::cout << std::endl;return 0;
}

额外知识

  • 仿函数的类型
#include <type_traits>
#include <iostream>struct F {int operator()(int) const {return 0;}
};int main() {F f;static_assert(!std::is_function<decltype(f)>::value);   // f不是函数static_assert(std::is_class<decltype(f)>::value);       // f是类static_assert(std::is_same<decltype(f), F>::value);     // f的类型是Fstd::cout << f(10) << std::endl;
}

仿函数的优势

  • 可扩展性: 能够根据需要添加更多功能和状态。
  • 与Lambda的互补性: 在需要携带复杂状态或多次调用时,仿函数比Lambda更适合。
  • 类型安全: 仿函数是具体的类型,可以在编译期进行类型检查。

何时使用仿函数

  • 需要携带状态时: 当回调函数需要维护内部状态时,仿函数是理想选择。
  • 复杂操作: 当简单的函数指针或Lambda难以表达复杂逻辑时。
  • 性能关键场景: 由于仿函数可以被编译器优化,适用于性能敏感的代码。

相关文章:

  • 【漫话机器学习系列】229.特征缩放对梯度下降的影响(The Effect Of Feature Scaling Gradient Descent)
  • 【氮化镓】质子辐照对 GaN-on-GaN PiN 二极管电导调制的影响
  • 专业测量中的示波器噪声抑制技巧
  • Docker镜像技术深度解析
  • 如何从大规模点集中筛选出距离不小于指定值的点
  • 如何理解promise 续二
  • Transformer数学推导——Q28 分析图注意力(Graph Attention)的邻接矩阵与注意力权重的等价条件
  • 在移动应用开发中,如何优化JavaScript的性能
  • [JavaScript]对象关联风格与行为委托模式
  • Spring MVC异常处理利器:深入理解HandlerExceptionResolver
  • 蚁群算法是一种模拟蚂蚁觅食行为的优化算法,适合用于解决旅行商问题(TSP)
  • PPO算法详解:强化学习策略优化的新高度
  • [26] cuda 应用之 nppi 实现图像格式转换
  • 静态库与动态库简介
  • 奥威BI+AI数据分析解决方案
  • Hadoop 单机模式(Standalone Mode)部署与 WordCount 测试
  • Linux网络编程:TCP多进程/多线程并发服务器详解
  • Coupang火箭计划深度攻略:eBay卖家突破韩国市场的三维数据作战模型
  • Python面试问题
  • mac 基于Docker安装minio服务器
  • 张元济和百日维新
  • 杭州一季度GDP为5715亿元,同比增长5.2%
  • 国家发改委答澎湃:将指导限购城市针对长期摇号家庭和无车家庭等重点群体定向增发购车指标
  • 上海“生育友好岗”已让4000余人受益,今年将推产假社保补贴政策
  • 影子调查|23岁男子驾照拟注销背后的“被精神病”疑云
  • 在差异中建共鸣,《20世纪美国文学思想研究》丛书出版