仿函数(Functor)是什么?
仿函数(Functor)
仿函数是通过重载()运算符的类或结构体的对象。这样一个对象可以像普通函数一样被调用。
仿函数通常用于需要在对象内部保留状态或多次调用时有特定行为的情况。
特点:
- 仿函数是一个类对象。
- 通过重载
()运算符使得类对象像函数一样可以被调用。 - 可以在类中保留状态或成员变量,提供比普通函数更复杂的逻辑和功能。
- 适合在需要复用逻辑和状态的场景中使用。
示例:
#include <iostream>
using namespace std;
class Adder {
public:
Adder(int x) : value(x) {}
// 重载 () 操作符,使对象能像函数一样调用
int operator()(int y) {
return value + y;
}
private:
int value;
};
int main() {
Adder add5(5); // 创建一个仿函数对象,初始值为5
cout << add5(10) << endl; // 输出 15
return 0;
}
Lambda 表达式
Lambda 表达式是一种匿名函数,可以在函数内定义一个临时的、无名的函数。
Lambda 表达式非常适合在简单的函数逻辑下使用,不需要事先定义一个函数名称。
它主要用于简化代码、捕获上下文环境中的变量、以及函数式编程等场景。
特点:
- Lambda 表达式是一个匿名函数,直接在使用的地方定义。
- 语法简洁,适合用于临时、一次性的小函数。
- 可以捕获外部作用域中的变量,提供便捷的上下文共享能力。
- 一般用于简单的逻辑处理,不需要复杂的状态保存。
Lambda 表达式的语法:
[capture](parameters) -> return_type {
// function body
};
示例:
#include <iostream>
using namespace std;
int main() {
int x = 10;
auto add = [x](int y) {
return x + y; // 捕获外部变量x
};
cout << add(5) << endl; // 输出 15
return 0;
}
仿函数与 Lambda 的区别
定义形式:
- 仿函数是通过类重载
()运算符实现的。 - Lambda 表达式是匿名函数,直接在使用时定义。
- 仿函数是通过类重载
状态管理:
- 仿函数类可以通过成员变量保存状态,适合需要在多次调用间保持状态的场景。
- Lambda 表达式可以通过捕获外部变量来实现类似的效果,但一般不会像仿函数那样专门用于状态管理。
灵活性:
- 仿函数可以通过类的复杂逻辑实现更灵活的功能。
- Lambda 表达式适合实现简单的逻辑,更加简洁明了。
适用场景:
- 仿函数更适合用于复杂的、需要状态维护的场景。
- Lambda 表达式适用于临时、轻量级的函数逻辑。
仿函数作为模板的默认形参,带来了以下几个好处:
1. 提高灵活性和可扩展性
仿函数相比普通函数更灵活,因为它们是类的对象,可以保存状态信息。作为模板的默认形参,仿函数允许在调用模板时传入不同的策略,而不需要更改代码逻辑。
#include <iostream>
#include <vector>
#include <algorithm>
// 定义一个仿函数
struct MultiplyByTwo {
int operator()(int x) const {
return x * 2;
}
};
// 模板函数,接受一个可调用对象
template<typename T, typename Func = MultiplyByTwo>
void transformVector(std::vector<T>& vec, Func func = Func()) {
std::transform(vec.begin(), vec.end(), vec.begin(), func);
}
int main() {
std::vector<int> v = {1, 2, 3, 4};
// 使用默认的仿函数 MultiplyByTwo
transformVector(v);
for (int i : v) {
std::cout << i << " "; // 输出: 2 4 6 8
}
std::cout << std::endl;
return 0;
}
好处:
- 默认使用
MultiplyByTwo仿函数来实现功能,避免了重复编写相同的逻辑。
-** 如果需要不同的行为,可以传递自定义的仿函数或普通函数**。例如,传入[](int x){ return x + 1; }这样的 lambda 表达式。
2. 支持状态的维护
仿函数可以存储状态信息,这意味着它们可以在多个调用之间共享数据。通
过仿函数,模板的默认形参不仅可以是单纯的行为,还可以携带状态信息,提供更高级的功能。
#include <iostream>
// 仿函数,带有状态信息
struct Adder {
int offset;
Adder(int o) : offset(o) {}
int operator()(int x) const {
return x + offset;
}
};
// 使用 Adder 仿函数作为默认参数
template<typename Func = Adder>
int addNumber(int x, Func func = Func(5)) { // 默认偏移量为5
return func(x);
}
int main() {
std::cout << addNumber(10) << std::endl; // 输出: 15
std::cout << addNumber(10, Adder(3)) << std::endl; // 输出: 13
return 0;
}
好处:
- 仿函数可以持有状态信息(如
offset),这在普通函数中是无法做到的。 - 默认情况下,可以使用带有特定状态的仿函数,如果需要自定义的行为,可以传递新的仿函数实例。
3. 使用 STL 容器和算法时的便利
在标准模板库(STL)中,许多算法接受仿函数作为参数,例如 std::sort、std::for_each 等。
使用仿函数作为模板的默认形参可以使得这些算法更加灵活和高效。
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义仿函数,判断是否是偶数
struct IsEven {
bool operator()(int x) const {
return x % 2 == 0;
}
};
// 过滤偶数的函数模板,使用仿函数作为默认参数
template<typename Func = IsEven>
std::vector<int> filterEven(const std::vector<int>& vec, Func func = Func()) {
std::vector<int> result;
std::copy_if(vec.begin(), vec.end(), std::back_inserter(result), func);
return result;
}
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5, 6};
// 使用默认的 IsEven 仿函数
std::vector<int> evens = filterEven(nums);
for (int n : evens) {
std::cout << n << " "; // 输出: 2 4 6
}
std::cout << std::endl;
return 0;
}
好处:
- STL 算法和容器结合仿函数使用非常方便,使代码简洁并保持高可读性。
将仿函数作为模板的默认形参的主要好处包括:
- 提高灵活性和可扩展性:可以根据需要传递不同的行为(仿函数、函数或 lambda 表达式)。
- 支持状态维护:仿函数可以携带状态信息,实现比普通函数更复杂的逻辑。
- 与 STL 算法结合:方便和高效的标准算法使用方式。
仿函数(Functor)是什么?的更多相关文章
- C++仿函数(functor)详解
C++仿函数(functor)详解 所谓的仿函数(functor),是通过重载()运算符模拟函数形为的类. 因此,这里需要明确两点: 1 仿函数不是函数,它是个类: 2 仿函数重载了()运算符,使得它 ...
- STL仿函数functor
一:仿函数functor介绍 尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象. functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的 ...
- function call操作符(operator()) 仿函数(functor)
主要是需要某种特殊的东西来代表一整组操作 代表一整组操作的当然是函数,过去通过函数指针实现 所以STL算法的特殊版本所接受的所谓条件或策略或一整组操作都以仿函数的形式呈现 #include <i ...
- 仿函数(functor)
仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了. In computer programmin ...
- C++ 谓词(predicate) 与 仿函数 ( functor (function object))
谓词与函数对象 谓词 predicate C++ 标准定义谓词如下: The Predicate parameter is used whenever an algorithm expects a f ...
- C++ STL 学习 :for_each与仿函数(functor)
简单来将,仿函数(functor)就是一个重载了"()"运算符的struct或class,利用对象支持operator()的特性,来达到模拟函数调用效果的技术. 我们平时对一个集合 ...
- c++仿函数 functor
内容整理自国外C++教材 先考虑一个简单的例子:假设有一个vector<string>,你的任务是统计长度小于5的string的个数,如果使用count_if函数的话,你的代码可能长成这样 ...
- 函数对象(仿函数 functor)
简单地说,函数对象就是一个重载了()运算符的类实例,它可以像一个函数一样使用. #include <iostream> using namespace std; class Add { p ...
- (六)STL仿函数functor
1.仿函数为算法服务,特点是重载操作符() 2.一共分为3大类,包括算术类,逻辑运算类,相对关系(比较大小):都继承了binary_function 3.仿函数的一些调用示例,其中右边的仿函数没有继承 ...
- STL六大组件之——仿函数偷窥
仿函数(functor),就是使一个类或类模板的使用看上去象一个函数.其实现就是类或类模板中对operator()进行重载,这个类或类模板就有了类似函数的行为.仿函数是智能型函数就好比智能指针的行为像 ...
随机推荐
- fasterWhisper和MoneyPrinterPlus无缝集成
MoneyPrinterPlus之前使用的是各种云厂商的语音识别服务来进行语音的视频和字幕的识别工作. 但是很多小伙伴说云服务用不起. 那么没办法,MoneyPrinterPlus上线最新版本,支持f ...
- browsermob-proxy-2.1.4启动失败,报错ProxyServerError: The Browsermob-Proxy server process failed to start
报错信息:ProxyServerError: The Browsermob-Proxy server process failed to start. Check <_io.TextIOWrap ...
- Jmeter函数助手14-TestPlanName
TestPlanName函数获取当前测试计划保存的文件名称.该函数没有参数,直接引用即可${__TestPlanName}.
- web3 产品介绍 Dune Analytics 区块链的数据探索和可视化 链上热点和趋势一手掌握
Dune Analytics 是一个强大的数据分析平台,旨在帮助用户在区块链上进行数据探索和可视化. Dune Analytics的特点: 数据查询与可视化:Dune Analytics允许用户从多个 ...
- 从.net开发做到云原生运维(六)——分布式应用运行时Dapr
1. 前言 上一篇文章我们讲了K8s的一些概念,K8s真的是带来了很多新玩法,就像我们今天这篇文章的主角Dapr一样,Dapr也能在K8s里以云原生的方式运行.当然它也可以和容器一起运行,或者是CLI ...
- 智能工业化的关键一环:sim2real的仿真环境设计
智能工业化,不论是智能机器人技术还是数字孪生技术,都不可避免的要使用的一个技术就是仿真环境技术. 在智能工业化还停留在学术阶段的时候,大家都可以使用一些开源的免费的仿真环境做research,但是到了 ...
- 1000T的文件怎么能快速从南京传到北京?最佳方案你肯定想不到
今天刷面试题看到一个有意思的面试题, 1000T的文件怎么能以最快速度从南京传到北京? 网络传输 首先我们考虑通过网络传输,需要多长时间. 我特地咨询了在运营商工作的同学,目前带宽: 家庭宽带下行最大 ...
- 关于EF延时加载的面试题
public async Task<ActionResult> GetData() { var data = (from leftdata in GetLeft() join rightd ...
- SparkStreaming本地化策略性能调优与使用场景分析
1.背景介绍:平台使用的华为FI C203的版本,通过SparkStreaming消费kafka数据后,进行算法处理入库.其中在算法部分耗时为4秒,每个批的数据量在30MB左右.执行算法部分的算子分区 ...
- React 高德地图 进京证 (二)
上回书说到,躲开摄像头的基本功能实现了,但有三个核心问题: (1)速度慢 (2)距离远易失败 (3)地图限制 第一个问题:较为简单,把几千个摄像头按行政区划分好带上编号,在路线分段避让时按片儿计算,综 ...