std::bind--改变函数参数的局限

news/2024/10/8 15:43:30/文章来源:https://www.cnblogs.com/niumachen/p/18451749

std::bind 是 C++ 标准库中的一个工具,用于将函数对象与部分参数绑定在一起,生成一个新的可调用对象。这使得函数的参数可以被部分或全部提前指定,从而得到一个参数更少甚至无参数的函数对象。在某些情况下,它可以用来延迟执行函数、简化函数调用,或在需要无参函数对象的场景中使用(如线程池、回调等)。

1. std::bind 的基本用法

std::bind 的主要作用是 预先绑定参数,让函数调用变得更简单。它返回一个 函数对象,你可以在稍后调用这个对象,或者传递给其他接受可调用对象的函数(例如 std::function、线程池等)。

基本语法:

std::bind(function, arg1, arg2, ..., argN);

其中,function 是你要调用的函数,arg1, arg2, ..., argN 是你要绑定到函数的参数。可以通过占位符 _1, _2, 等等,来表示哪些参数将在调用时由用户提供,而哪些参数是提前绑定的。

示例:

#include <iostream>
#include <functional>  // std::bindvoid add(int a, int b) {std::cout << a + b << std::endl;
}int main() {auto bound_func = std::bind(add, 10, std::placeholders::_1);bound_func(20);  // 相当于调用 add(10, 20)
}

在这个例子中,std::bind 将函数 add 的第一个参数固定为 10,第二个参数由调用时提供。调用 bound_func(20) 时,相当于调用 add(10, 20)

2. 应用场景

std::bind 主要用于以下几种场景:

1. 延迟执行

有时你希望将函数的执行推迟到以后,或者希望把一个带参数的函数简化成不带参数的函数供以后使用。这在需要无参函数对象的场合(如线程、回调、事件处理等)尤为有用。

#include <iostream>
#include <functional>void greet(std::string name) {std::cout << "Hello, " << name << "!" << std::endl;
}int main() {auto greet_func = std::bind(greet, "Alice");greet_func();  // 延迟执行,输出:Hello, Alice!
}

2. 简化回调或线程函数

在很多异步编程场景下(如多线程、事件回调),常常需要传递一个不带参数的回调函数。std::bind 可以让你将带参数的函数转换为无参数的形式,非常适合线程池、std::function<void()> 回调等场景。

#include <iostream>
#include <thread>
#include <functional>void task(int x) {std::cout << "Task with value: " << x << std::endl;
}int main() {std::thread t(std::bind(task, 42));  // 将带参数的函数 task 变成无参调用t.join();
}

3. 适用于标准库中的函数对象(如 std::function

std::bind 非常适合与 std::function 配合使用,尤其是当你需要一个泛型的可调用对象,并且需要部分参数绑定时。

#include <iostream>
#include <functional>void multiply(int a, int b) {std::cout << a * b << std::endl;
}int main() {std::function<void(int)> mul_by_two = std::bind(multiply, 2, std::placeholders::_1);mul_by_two(5);  // 输出:10
}

在这个例子中,mul_by_two 是一个 std::function<void(int)>,它将参数 a 固定为 2,调用时只需要传递 b

4. 配合成员函数

std::bind 也可以与类的成员函数一起使用,可以绑定一个类的对象实例,或者通过占位符 _1 等动态传递对象实例。

#include <iostream>
#include <functional>class MyClass {
public:void print_sum(int a, int b) {std::cout << "Sum: " << a + b << std::endl;}
};int main() {MyClass obj;auto bound_func = std::bind(&MyClass::print_sum, &obj, 10, 20);  // 绑定成员函数bound_func();  // 输出:Sum: 30
}

3. 解决的问题

std::bind 解决了在以下几个方面的编程难题:

  1. 参数绑定:允许你预先绑定部分或全部参数,以减少函数调用时的参数数量。
  2. 简化函数签名:当使用标准库中的通用接口(如 std::function、线程、回调等)时,std::bind 使得你可以将复杂的函数转换为简单的无参或少参数形式。
  3. 延迟调用:通过捕获和绑定参数,可以在某些特定的场景下(如异步执行)延迟函数的执行,而不必立刻调用。

4. 缺点与替代品

尽管 std::bind 功能强大,但它也有一些缺点:

  • 可读性差std::bind 的使用可能会导致代码变得晦涩难懂,尤其是涉及到大量占位符时。
  • 性能问题std::bind 可能比直接使用 Lambda 表达式略慢,尤其是在简单场景下。

因此,在很多情况下,Lambda 表达式std::bind 的更好的替代品,尤其是在 C++11 及之后的版本中。

auto lambda_func = [=](int b) { return multiply(2, b); };
lambda_func(5);

这个 Lambda 表达式可以代替 std::bind,更直观和简洁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/809996.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入了解Oracle OCP认证,开启数据库专业之旅

使用Oracle数据库的公司内部,经常有员工们在讨论OCP认证(Oracle Certified Professional,Oracle认证专家),这是甲骨文Oracle公司提供的一种专业认证,认证用于使用者在Oracle技术领域的专业知识和技能。 在这里,有一点需要大家知道,虽然OCP认证一般指的是Oracle数据库管理…

vue2项目 一直报ts-plugin错误

如图,项目代码未动,突然代码报错,运行没问题不受影响 经排查,插件Vue-Official版本问题 ,问题版本v2.1.6 解决版本,安装其他版本 ,v1.8.27 作者:听着music睡出处:http://www.cnblogs.com/xqxacm/Android交流群:38197636本文版权归作者和博客园共有,欢迎转载,但未经…

鼠标的移入、移出事件

原文链接:鼠标的移入、移出事件_鼠标移入事件-CSDN博客

初识Rancher

一、简介 1、什么是rancher Rancher是一个开源软件平台,使组织能够在生产中运行和管理Docker和Kubernetes。使用Rancher,组织不再需要使用一套独特的开源技术从头开始构建容器服务平台。Rancher提供了管理生产中的容器所需的整个软件堆栈。  2、充分发挥K8s的潜力 Kubernete…

Linux下操作Nginx相关命令

1、查看Nginx进程 ps -aux | grep nginx圈出的就是Nginx的二进制文件 2、测试Nginx配置文件 /usr/sbin/nginx -t可以看到nginx配置文件位置 3、nginx的使用(启动、重启、关闭) 首先利用配置文件启动nginx。nginx -c /usr/local/nginx/conf/nginx.conf重启服务:service nginx r…

10月8号笔记

1.StringUtil常用方法2.判断不为空:CollectionUtils.isNotEmpty():集合不为空; StringUtils.isNotBlank():String不为空; MapUtils.isNotEmpoty():Map集合判断不为空;3."::"用法:4.getRecords()用法:5.MyBatis-Plus常用方法:6.MyBatis-Plus中Page与IPage的区…

夜莺监控的机器支持挂载到多个业务组了

夜莺开源项目于国庆前夕发布了 v7.4.1 版本,修复了一些 bug,同时也带来了一些新功能。其中最重要的一个功能是:机器支持挂载到多个业务组了。本文将介绍几个重要的变更。 所有变更点feat: 左侧栏业务组新设计 feat: 机器支持了绑定到多个业务组,机器混部的场景,管理机器更…

SS241007C. 步行(walk)

待订正。SS241007C. 步行(walk) 题意 给你一个 \(n \le 3 \times 10^5\) 个结点的树,每个结点有一个权值 \(a_i\)。有 \(m \le 1.5 \times 10^6\) 次询问,每次删除一条边,然后再连上一条边。如果修改后的图不是树输出无解。否则找出一条路径,满足每个点恰好经过 \(a_i\) …

day02_基本的DOS命令

电脑常用快捷键 常用快捷键快捷键 作用CTRL + c 复制CTRL + v 粘贴CTRL + x 剪切CTRL + z 撤销CTRL + s 保存alt + f4 关闭窗口del 删除shift + del 强制删除Windows + r 打开 “运行” 窗口windows + e 打开 “我的文档”ctrl + alt + del 锁定/切换用户/注销/更改密码/任务管…

组态也能开发WEB前端 | uiotos致敬amis、nodered、appsmith、codewave、goview、dataroom、iotrouter、FUXA、乐吾乐

WEB组态开发SCADA、HMI画面、大屏可视化,还比较常见。比如下面: UIOTOS组态示例 那么常规WEB前端功能,组态能否一并做了呢?比如下面这种: UIOTOS前端示例 答案是可以的!UIOTOS支持页面无限嵌套,能实现原型即应用。现在就以一个具体小示例介绍如何实现的。 效果 如下所示…

GUI无代码小示例 - 工作流连线实现0/1连续翻转

效果 如下所示,连续点击按钮,输出0、1、0、1...。 步骤新建页面,拖入组件拖入3个组件:数学计算、输入框、按钮。如下所示: 连线和配置按钮点击 → 函数执行1减去输入,作为函数输出这样,当首次执行时,默认操作数1将减去输入的1,输出0。 函数输出→ 输入框 → 函数输入 …