仿函数(Functor)

仿函数是通过重载()运算符类或结构体的对象。这样一个对象可以像普通函数一样被调用。

仿函数通常用于需要在对象内部保留状态或多次调用时有特定行为的情况。

特点:

  1. 仿函数是一个类对象。
  2. 通过重载 () 运算符使得类对象像函数一样可以被调用。
  3. 可以在类中保留状态或成员变量,提供比普通函数更复杂的逻辑和功能。
  4. 适合在需要复用逻辑和状态的场景中使用。

示例:

#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 表达式非常适合在简单的函数逻辑下使用,不需要事先定义一个函数名称。

它主要用于简化代码、捕获上下文环境中的变量、以及函数式编程等场景。

特点:

  1. Lambda 表达式是一个匿名函数,直接在使用的地方定义。
  2. 语法简洁,适合用于临时、一次性的小函数。
  3. 可以捕获外部作用域中的变量,提供便捷的上下文共享能力。
  4. 一般用于简单的逻辑处理,不需要复杂的状态保存。

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 的区别

  1. 定义形式

    • 仿函数是通过类重载 () 运算符实现的。
    • Lambda 表达式是匿名函数,直接在使用时定义。
  2. 状态管理

    • 仿函数类可以通过成员变量保存状态,适合需要在多次调用间保持状态的场景。
    • Lambda 表达式可以通过捕获外部变量来实现类似的效果,但一般不会像仿函数那样专门用于状态管理。
  3. 灵活性

    • 仿函数可以通过类的复杂逻辑实现更灵活的功能。
    • Lambda 表达式适合实现简单的逻辑,更加简洁明了。
  4. 适用场景

    • 仿函数更适合用于复杂的、需要状态维护的场景。
    • 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::sortstd::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 算法和容器结合仿函数使用非常方便,使代码简洁并保持高可读性。

将仿函数作为模板的默认形参的主要好处包括:

  1. 提高灵活性和可扩展性:可以根据需要传递不同的行为(仿函数、函数或 lambda 表达式)。
  2. 支持状态维护:仿函数可以携带状态信息,实现比普通函数更复杂的逻辑。
  3. 与 STL 算法结合:方便和高效的标准算法使用方式。

仿函数(Functor)是什么?的更多相关文章

  1. C++仿函数(functor)详解

    C++仿函数(functor)详解 所谓的仿函数(functor),是通过重载()运算符模拟函数形为的类. 因此,这里需要明确两点: 1 仿函数不是函数,它是个类: 2 仿函数重载了()运算符,使得它 ...

  2. STL仿函数functor

    一:仿函数functor介绍 尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象. functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的 ...

  3. function call操作符(operator()) 仿函数(functor)

    主要是需要某种特殊的东西来代表一整组操作 代表一整组操作的当然是函数,过去通过函数指针实现 所以STL算法的特殊版本所接受的所谓条件或策略或一整组操作都以仿函数的形式呈现 #include <i ...

  4. 仿函数(functor)

    仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了. In computer programmin ...

  5. C++ 谓词(predicate) 与 仿函数 ( functor (function object))

    谓词与函数对象 谓词 predicate C++ 标准定义谓词如下: The Predicate parameter is used whenever an algorithm expects a f ...

  6. C++ STL 学习 :for_each与仿函数(functor)

    简单来将,仿函数(functor)就是一个重载了"()"运算符的struct或class,利用对象支持operator()的特性,来达到模拟函数调用效果的技术. 我们平时对一个集合 ...

  7. c++仿函数 functor

    内容整理自国外C++教材 先考虑一个简单的例子:假设有一个vector<string>,你的任务是统计长度小于5的string的个数,如果使用count_if函数的话,你的代码可能长成这样 ...

  8. 函数对象(仿函数 functor)

    简单地说,函数对象就是一个重载了()运算符的类实例,它可以像一个函数一样使用. #include <iostream> using namespace std; class Add { p ...

  9. (六)STL仿函数functor

    1.仿函数为算法服务,特点是重载操作符() 2.一共分为3大类,包括算术类,逻辑运算类,相对关系(比较大小):都继承了binary_function 3.仿函数的一些调用示例,其中右边的仿函数没有继承 ...

  10. STL六大组件之——仿函数偷窥

    仿函数(functor),就是使一个类或类模板的使用看上去象一个函数.其实现就是类或类模板中对operator()进行重载,这个类或类模板就有了类似函数的行为.仿函数是智能型函数就好比智能指针的行为像 ...

随机推荐

  1. 使用 Doxygen 来生成 Box2d 的 API 文档

    对于 Doxygen 以前只听别人说过,而现在使用它也是一个偶然,缘分吧.前两天看 box2d 的官方 sdk 中,发现他有用户手册却没有说明,只是留下了一个 Doxygen 的文件.事情告一段落,然 ...

  2. ffmpeg中声音解码的流程

    声音解码流程: audio初始化 fifo初始化frame初始化init_resampler 解码: 如果有帧 初始化转码空间 做转码操作 resampler 放入fifo fifo是否大于 一帧数据 ...

  3. mysql 参数调优

    临时调整mysql内存,最好在项目开始的时候直接改配置不用临时设置 SET GLOBAL innodb_buffer_pool_size = 2147483648; 查询当前使用内存: SHOW VA ...

  4. 【Uni-App】其他配置笔记

    manifest.json manifest.json 文件是应用的配置文件,用于指定应用的名称.图标.权限等.HBuilderX 创建的工程此文件在根目录,CLI 创建的工程此文件在 src 目录. ...

  5. 连接huggingface.co报错:(MaxRetryError("SOCKSHTTPSConnectionPool(host='huggingface.co', port=443) (SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1007)

    参考: https://blog.csdn.net/shizheng_Li/article/details/132942548 https://blog.csdn.net/weixin_4220944 ...

  6. Ubuntu Server无桌面无显示器情况下虚拟屏幕xvfb的安装及设置—ubuntu18.04server服务器系统下为python安装虚拟显示器 (使用jupyter notebook在web端播放openai的gym下保存的运行视频——需安装ipython)

    1.  安装xvfb sudo apt-get install xvfb Xvfb是流行的虚拟现实库,可以使很多需要图形界面的程序虚拟运行. 2. 安装pyvirtualdisplay pyvirtu ...

  7. python报错:pyglet.canvas.xlib.NoSuchDisplayException: Cannot connect to "None"

    运行python代码报错: 问题发现: 问题其实十分的狗血,这个代码是在服务器上运行的,运行之前其实并没有看具体的代码情况,git clone 下载下来就直接运行了,原来这个代码需要进行图片绘制,说直 ...

  8. No such file or directory: 'patchelf': 'patchelf'

    安装mujoco报错: No such file or directory: 'patchelf': 'patchelf' 解决方法: sudo apt-get install patchelf

  9. 手把手教你掌握SeaTunnel k8s运行Zeta引擎本地模式的技巧

    转载自小虾米0.0 导读:随着Kubernetes的普及和发展,越来越多的企业和团队开始使用Kubernetes来管理和部署应用程序.然而,Kubernetes的默认工作方式可能不是最佳的选择,尤其是 ...

  10. 【Playwright+Python】系列教程(八)鉴权Authentication的使用

    写在前面 还是有些絮叨的感觉,官方翻译和某些博主写那个玩楞,基本都是软件直接翻译后的产物. 读起来生硬不说,甚至有的时候不到是什么意思,真的是实在不敢恭维. 到底是什么意思? 就是你已经登陆过一次,在 ...