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

C++std::function和std::bind()的概念

std::function: 一个通用的函数封装器,它允许你存储和调用任何可以被调用的东西,例如函数、函数指针、函数对象、Lambda 表达式等。

std::bind: 用于创建函数对象。一个可调用对象的绑定版本,可以提前绑定某些参数,稍后调用时只需提供剩余的参数。
在某些情况下,你可以将它们结合使用,例如,如果你想创建一个可调用对象,该对象包含绑定的参数,然后将其存储在 std::function 中。这在某些情况下可以提高代码的可读性和灵活性。

示例:

#include <iostream>
#include <functional>int add(int a, int b) {return a + b;
}int main() {// 创建一个绑定了参数的可调用对象,绑定参数为2,// 占位符_1表示稍后调用时传入的第1个参数放在_1这个位置std::function<int(int)> func = std::bind(add, 2, std::placeholders::_1);// 调用 std::functionint result = func(3); // 这里相当于调用 add(2, 3)std::cout << "Result: " << result << std::endl;return 0;
}

将std::function与std::bind一起使用可以提供一些好处,尤其在以下情况下:

  • 延迟参数绑定:你可以使用std::bind在创建std::function对象时部分绑定参数,然后稍后再提供其余的参数。这使得你可以在调用可调用对象时动态地确定一些参数值。

  • 增强可读性:std::bind允许你清晰地指定参数的绑定方式,这可以提高代码的可读性,特别是当你处理复杂的函数签名时。

  • 灵活性:结合使用std::function和std::bind可以让你更容易地操作和传递可调用对象。这对于实现通用接口或处理回调函数时特别有用。

  • 减少代码冗余:如果你需要多次调用具有相同部分绑定的可调用对象,结合使用std::function和std::bind可以减少重复的绑定代码。

在不需要提前绑定参数的情况下,可以不使用std::bind()。在C++11引入Lambda表达式后,使用更加灵活和方便。以下是一个示例,演示如何使用 std::function 存储一个普通函数或Lambda表达式

Copy code
#include <iostream>
#include <functional>// 普通函数
int add(int a, int b) {return a + b;
}int main() {// 使用 std::function 存储普通函数std::function<int(int, int)> func1 = add;// 使用 Lambda 表达式std::function<int(int, int)> func2 = [](int a, int b) {return a + b;};int result1 = func1(2, 3); // 调用 add 函数int result2 = func2(4, 5); // 调用 Lambda 表达式std::cout << "Result 1: " << result1 << std::endl;std::cout << "Result 2: " << result2 << std::endl;return 0;
}

考虑这种情况:可调用对象是类的普通成员函数

  • 成员函数是跟具体的对象绑定的,它可以操作该对象中的其他成员变量或者调用其他成员函数。成员函数可以做到分辨哪个对象在调用我是因为有隐藏this指针指向当前调用该函数的对象。
  • 比如obj.funcAdd(1,2),效果实际上是Obj::funcAdd(&obj, 1, 2);
  • 因此如果可调用对象是普通成员函数,我们要绑定一个参数,即指向调用对象的指针。

因此,比较推荐std::function与std::bind()配合使用,或者用lambda表达式

  • 当在一个成员函数中创建函数指针指向另一个普通成员函数时,绑定参数为this

    #include <iostream>
    #include <functional>class MyClass {
    public:void func1(int value) {std::cout << "func1: " << value << std::endl;}void func2(int value) {std::cout << "func2: " << value << std::endl;}void doSome() {// 使用 std::bind 创建 std::function 对象,将其绑定到 func2std::function<void(MyClass*, int)> functionPtr = std::bind(&MyClass::func2, this, std::placeholders::_2);// 调用函数指针,传入对象实例指针和参数functionPtr(42);}
    };int main() {MyClass obj;obj.doSome();return 0;
    }
    

    当然也可以手动传入this
    比如:std::bind(&MyClass::func2, std::placeholders::_1, std::placeholders::_2);
    调用:functionPtr(this, 42);

  • 利用lambda表达式作为可调用对象

    #include <iostream>
    #include <functional>class MyClass {
    public:void func1(int value) {std::cout << "func1: " << value << std::endl;}void func2(int value) {std::cout << "func2: " << value << std::endl;}void doSome() {// 使用 Lambda 表达式捕获 this 指针std::function<void(int)> functionPtr = [this](int value) {MemberFunction2(value);};// 调用函数指针,不需要传递 this 指针functionPtr(42);}
    };int main() {MyClass obj;obj.doSome();return 0;
    }
    
  • 还有一种简单的情况:如果是在想存储某个对象的某个成员函数的指针,则需要传入该对象的地址

    #include <iostream>
    #include <functional>class MyClass {
    public:void func(int value) {std::cout << "func: " << value << std::endl;}
    };int main() {MyClass obj;// 创建 std::function 对象,提前绑定&obj,如果不绑定则需要手动传入std::function<void(int)> funcPtr = std::bind(&MyClass::func, &obj, std::placeholders::_1);funcPtr(42);return 0;
    }
    

相关文章:

C++std::function和std::bind()的概念

std::function&#xff1a; 一个通用的函数封装器&#xff0c;它允许你存储和调用任何可以被调用的东西&#xff0c;例如函数、函数指针、函数对象、Lambda 表达式等。 std::bind&#xff1a; 用于创建函数对象。一个可调用对象的绑定版本&#xff0c;可以提前绑定某些参数&am…...

QT Creator工具介绍及使用

一、QT的基本概念 QT主要用于图形化界面的开发&#xff0c; QT是基于C编写的一套界面相关的类库&#xff0c;如进程线程库&#xff0c;网络编程的库&#xff0c;数据库操作的库&#xff0c;文件操作的库等。 如何使用这个类库&#xff1a;类库实例化对象(构造函数) --> 学习…...

python爬虫13:pymysql库

python爬虫13&#xff1a;pymysql库 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生…...

权限管理 ACL、RBAC、ABAC的学习

ACL(Access Control List&#xff1a;访问控制列表) 最简单的一种方式&#xff0c;将权限直接与用户或用户组相关联&#xff0c;管理员直接给用户授予某些权限即可。 这种模型适用于小型和简单系统&#xff0c;权限一块较为简单&#xff0c;并且角色和权限的变化较少。 RBAC(R…...

python的re正则表达式

一、正在表达式的方法&#xff08;&#xff09;&#xff1a; re是Python中用于处理正则表达式的内置库&#xff0c;提供了许多有用的方法。以下是其中几个常用的方法&#xff1a; re.match(pattern, string): 尝试从字符串的开头匹配一个模式&#xff0c;如果匹配成功则返回匹…...

【算法与数据结构】700、LeetCode二叉搜索树中的搜索

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;二叉搜索树的性质&#xff1a;左节点键值 < 中间节点键值 < 右节点键值。那么我们根据此性质&am…...

SpringBoot v2.7.x+ 整合Swagger3入坑记?

目录 一、依赖 二、集成Swagger Java Config 三、配置完毕 四、解决方案 彩蛋 想尝鲜&#xff0c;坑也多&#xff0c;一起入个坑~ 一、依赖 SpringBoot版本&#xff1a;2.7.14 Swagger版本&#xff1a;3.0.0 <dependency><groupId>com.github.xiaoymin<…...

说说你了解的 CDC

分析&回答 什么是 CDC CDC,Change Data Capture,变更数据获取的简称&#xff0c;使用CDC我们可以从数据库中获取已提交的更改并将这些更改发送到下游&#xff0c;供下游使用。这些变更可以包括INSERT,DELETE,UPDATE等。用户可以在以下的场景下使用CDC&#xff1a; 使用f…...

SpingMvc入门

SpingMvc入门 1.MVC Spring的工作流程&#xff1a;2.sping mvc入门3.静态资源处理 前言 Spring MVC是一种基于Java的web应用开发框架&#xff0c;它采用了MVC&#xff08;Model-View-Controller&#xff09;设计模式来帮助开发者组织和管理应用程序的各个组件。 1.MVC Spring的…...

JVM的故事——类文件结构

类文件结构 文章目录 类文件结构一、概述二、无关性基石三、Class类文件的结构 一、概述 计算机是只认由0、1组成的二进制码的&#xff0c;不过随着发展&#xff0c;我们编写的程序可以被编译成与指令集无关、平台中立的一种格式。 二、无关性基石 对于不同平台和不同平台的…...

springboot自定义表格(动态合并单元格)

一、需求展示&#xff08;一个订单多个商品&#xff0c;商品数量不限订单行合并&#xff09; 二、技术选型&#xff08;jxls自定义模板&#xff09; <!-- 版本具体看官网Release&#xff0c;这里我们使用 2.13.0 --><dependency><groupId>org.jxls</group…...

C++零碎记录(二)

3. 调用其他类 3.1 类中有其他的类 #include <iostream> using namespace std;//点和圆关系案例//点类 class Point { public://设置xvoid setX(int x){m_X x;}//获取xint getX(){return m_X;}//设置yvoid setY(int y){m_Y y;}//获取yint getY(){return m_Y;}private…...

数学建模:回归分析

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 数学建模&#xff1a;回归分析 文章目录 数学建模&#xff1a;回归分析回归分析多元线性回归案例 多项式回归一元多项式回归多元二项式回归 非线性回归逐步回归 回归分析 多元线性回归 案例 首先进行回归分…...

数据库(一)

数据库 1.为什么要使用数据库 如果要存储数据&#xff0c;我们是可以使用文件来存储数据的&#xff0c;但是使用文件管理数据有很多缺点&#xff0c;比如&#xff1a; 不安全&#xff0c;不利于管理&#xff0c;查询&#xff0c;如果要存储大量的数据&#xff0c;使用文件管理…...

【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;首先我们要知道后序遍历数组的最后一个元素必然是根节点&#xff0c;然后根据根节点在中序遍历数组中的…...

kali 安装cpolar内网穿透实现 ssh 远程连接

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过cpolar 内网穿透软件实现ssh 远程连接kali! 1. 启动kali ssh 服务 默认新安装的kali系统会关闭ssh 连接服务,我们通…...

算法训练 第一周

一、合并两个有序数组 本题给出了两个整数数组nums1和nums2&#xff0c;这两个数组均是非递减排列&#xff0c;要求我们将这两个数组合并成一个非递减排列的数组。题目中还要求我们把合并完的数组存储在nums1中&#xff0c;并且为了存储两个数组中全部的数据&#xff0c;nums1中…...

软件评测师之码制

目录 一、机器数二、码制三、数的表示范围 一、机器数 机器数就是一个数在计算机中的二进制表示&#xff0c;计算机中机器数的最高位是符号位&#xff0c;正数符号位为0&#xff0c;负数符号位为1&#xff0c;机器数包含原码、反码和补码三种表示形式。 二、码制 表现形式数…...

ubuntu18安装cmake27的方法

背景是ubuntu18默认的cmake是3.10 $ apt search cmake Sorting... Done Full Text Search... Done bear/bionic,bionic 2.3.11-1 allgenerate compilation database for Clang toolingcatkin/bionic,bionic 0.7.8-1 allLow-level build system macros and infrastructure for …...

通讯编程006——NodeJS OPC UA Client开发简单教程

本文介绍如何在NodeJS环境下开发OPC UA Client&#xff0c;通过本文可以对OPC UA的基本概念有所了解&#xff0c;掌握OPC UA的本质。相关软件请登录网信智汇(wangxinzhihui.com)。 开发步骤如下&#xff1a; 1&#xff09;首先需要安装nodejs&#xff0c;要求版本至少是12。 …...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...