仿函数(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()进行重载,这个类或类模板就有了类似函数的行为.仿函数是智能型函数就好比智能指针的行为像 ...
随机推荐
- 深度解读GaussDB(for MySQL)与MySQL的COUNT查询并行优化策略
本文分享自华为云社区<[华为云MySQL技术专栏]GaussDB(for MySQL)与MySQL的COUNT查询并行优化策略>,作者:GaussDB 数据库. 1.背景介绍 统计表的行数 ...
- 使用ollama本地部署gemma记录
1.官网https://ollama.com/安装ollama 2.先配置一下环境变量 不然下载的东西会默认丢在C盘里 3.cmd执行ollama run gemma:2b (使用后推荐直接下7b,2 ...
- 神经网络之卷积篇:详解计算机视觉(Computer vision)
详解计算机视觉 计算机视觉是一个飞速发展的一个领域,这多亏了深度学习.深度学习与计算机视觉可以帮助汽车,查明周围的行人和汽车,并帮助汽车避开它们.还使得人脸识别技术变得更加效率和精准,即将能够体验到或 ...
- pycham配置GitHub环境【一文了解window上GitHub的基本操作】
基础用户设置[包含用户登录.密钥生成] 网络配置 外观->系统设置->https代理->检查连接 我这里测试网址是GitHub,连接成功即可后续操作[不成功别找我,我也不知道] gi ...
- Ubuntu 18.04.4 导入docker镜像,启动镜像,保存容器为镜像,导出镜像
1. 查看 docker 版本 sudo docker version 2. 查看本地库中的镜像 sudo docker images 3. 查看 正在运行的 容器 sudo docker ...
- baselines算法库common/atari_wrappers.py模块分析
common/atari_wrappers.py模块代码如下: import numpy as np import os os.environ.setdefault('PATH', '') from ...
- CF1992场题解
Only Pluses 算法:数学. 题意简述:有三个数,每次选择一个数 \(x\),使得 \(x\) 增加一,至多操作 \(5\) 次,最后求出这三个数的乘积最大值. 简单题,一眼秒了.考虑把这 \ ...
- 旋转数组-python
旋转数组 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向 ...
- 实习记录day03:尝试写一个接口
前言:今天突然意识到,实习记录很少有技术性的东西,更多的是自己的心里活动和一些感想,其实这类博客更趋向于日记而非技术记录.也许哪天不再充满兴趣了,这个实习记录也就结束了(想下班了同志们) 实习第三天: ...
- 这次轮到AntV增强Awesome-Graphs
前不久,Awesome-Graphs刚Release完1.1.0版本后,我在<从论文到图谱,或许只差一个html>一文中,向大家详细展示了Awesome-Graphs的产品能力与交互形态. ...