现代 C++ 小利器:参数绑定包装器堪称「Lambda 小平替」

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/gt_zxMwhu8UixzCMF73Dng

C++ 原生支持函数输入参数的默认值,但是有些业务场景下对原有设定的默认值不满意,那么可不可以临时改改?

请注意,随意改变原有代码逻辑,并不符合软件设计原则。有没有什么方案或者特性可以做到不修改原有代码逻辑,以实现新增参数默认值(或者在调用时绑定特性参数)的功能?

从 C++11 开始,标准库提供了 std::bind 用于绑定函数 f 和调用参数,返回一个新可调用函数对象 fn (也有喊它做仿函数的)。于是,在调用函数对象 fn 和输入新参数时,相当于调用了原来的函数 f 并自动按照绑定的关系映射参数,映射的方式非常灵活。这样被绑定映射的参数,实现原有函数 f 的参数新默认值功能,或者减少调用函数 f 时输入的参数个数等便捷需求。

简而言之,std::bind 被称为转发调用包装器。

绑定时,通过占位符 _1, _2, _3… ,指定在调用函数对象 fn 的输入参数和传递给函数 f 的参数之间的映射位置。

被绑定的函数 f 也分种类,那么,基于不同类型函数的应用示例是怎样的呢?

绑定静态或者全局函数

#include <functional>void output1(int a)
{printf("%d\n", a);
}void output2(int a, int b)
{printf("%d %d\n", a, b);
}int main(int argc, char * argv[])
{auto fn1 = std::bind(output1, std::placeholders::_1);fn1(1);auto fn2 = std::bind(output2, std::placeholders::_2, 0);fn2(3, 2);return 0;
}

output:

1
2 0

占位符代表函数对象的输入参数,std::placeholders::_1 对应调用函数对象 fn 时的第 1 个输入参数,依次类推。

细心的你可能会留意 std::bind 返回的是可调用对象,这个和同样从 C++11 开始引入的 Lambda 表达式概念是类似的,那么有没有可能用 Lambda 表达式互相替换?试试改为使用 Lambda 表达式实现

int main(int argc, char * argv[])
{auto fn1 = [](int a) -> void {output1(a);};fn1(1);auto fn2 = [](int a, int b) -> void {output2(b, 0);};fn2(3, 2);return 0;
}

这样子替换后,执行输出结果是一样的。

output:

1
2 0

绑定对象成员函数

如果被绑定的函数是对象成员,需要指定所属对象,看代码

#include <functional>class A
{
public:void output(int a, int b){printf("%d %d\n", a, b);}
};int main(int argc, char * argv[])
{A obj;auto fn = std::bind(&A::output, &obj, std::placeholders::_2, std::placeholders::_1);fn(5, 3);return 0;
}

output:

3 5

用 Lambda 表达式替换试试

int main(int argc, char * argv[])
{A obj;auto fn = [&obj](int a, int b) -> void {obj.output(b, a);};fn(5, 3);return 0;
}

output:

3 5

Notice:绑定的时候需要指定上下文环境(实例对象),这种场景已经涉及到闭包的概念了。由于上下文环境是有生命周期的,比如上面用到的实例对象 a,如果在超出了其生命周期的情况下,引用其内部已被释放的资源,是会引起程序执行异常的,这里提醒一下。

平替 Lambda

以上面两种场景示例代码的比较,在参数绑定的场景下,为了达到相同效果,Lambda 表达式的书写略显罗嗦,而 std::bind 的格式更有函数式编程的味道,可见,某些场景下推荐 std::bind 替代 Lambda 表达式。

能不能平替也分场景,三思而行。

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

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

相关文章

听GPT 讲Rust源代码--compiler(22)

File: rust/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs rust/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs 文件是 Rust 编译器针对 x86_64-unknown-netbsd 目标平台的配置文件。该文件定义了与该平台相关的特性、链接选项、目标特定的运行时支持以…

安全与认证Week3 Tutorial+历年题补充

目录 1) 什么是重放攻击? 2)什么是Kerberos系统?它提供什么安全服务? 3)服务器验证客户端身份的一种简单方法是要求提供密码。在Kerberos中不使用这种身份验证&#xff0c;为什么?Kerberos如何对服务器和客户机进行身份验证? 4) Kerberos的四个要求是什么?Kerberos系…

速记计算机网络传输介质分类

计算机网络中的传输介质是指用于在不同设备之间传递数据的物理媒介。传输介质的选择对于网络的性能和可靠性至关重要。在计算机网络中&#xff0c;常见的传输介质可以分为有线传输介质和无线传输介质两类。本文将对这两类传输介质进行详细的分类和介绍。 一、有线传输介质 有…

全新的C++语言

一、概述 C 的最初目标就是成为 “更好的 C”&#xff0c;因此新的标准首先要对基本的底层编程进行强化&#xff0c;能够反映当前计算机软硬件系统的最新发展和变化&#xff08;例如多线程&#xff09;。另一方面&#xff0c;C对多线程范式的支持增加了语言的复杂度&#xff0…

Docker overlay2文件busy,容器不能删除问题解决

文章目录 在删除docker容器的时候报错,说设备正忙通过 docker ps -a 查看有两个状态的dead的容器解决方法&#xff1a;1.查看所有挂载的设备2.截取设备的进程id3.清理进程(kill掉即可) 在删除docker容器的时候报错,说设备正忙 Error response from daemon: Driver overlay2 fai…

[CISCN 2019华东南]Web11

[CISCN 2019华东南]Web11 wp 信息搜集 页面内容如下&#xff1a; 右上角显示的是我的当前 IP 。 在最下角提示&#xff1a;Build With Smarty ! Smarty 是 PHP 的一个模板引擎&#xff0c;那么这道题应该是 Smarty 模板注入。 Smarty 模板注入 可以参考博客&#xff1a;Sm…

一文弄懂vue中样式穿透v-deep

1. 前言 在vue3的世界里&#xff0c;有一个style标签的关键字v-deep&#xff0c;官网称之为样式穿透。那他究竟是什么原理呢&#xff1f;又是怎么工作的呢&#xff1f;让我们一起探究一下。 2. 准备工作 需要实现搭建一个vue3的环境&#xff0c;我这里使用的是vitevue3的架构…

QT工具栏开始,退出

QT工具栏开始&#xff0c;退出 //初始化场景QMenuBar *bar menuBar();setMenuBar(bar);QMenu *startbar bar->addMenu("开始");QAction * quitAction startbar->addAction("退出");connect(quitAction , &QAction::triggered,[](){this->c…

Transformer 的双向编码器表示 (BERT)

一、说明 本文介绍语言句法中&#xff0c;最可能的单词填空在self-attention的表现形式&#xff0c;以及内部原理的介绍。 二、关于本文概述 在我之前的博客中&#xff0c;我们研究了关于生成式预训练 Transformer 的完整概述&#xff0c;关于生成式预训练 Transformer (GPT) 的…

无心剑汉英双语诗《一亩三分地》

一亩三分地 My Small World 二十四年世事变幻 拨号上网曾争分夺秒 如今不限流量肆意冲浪 大数据&#xff0c;云计算&#xff0c;人工智能 洗刷着世间各行各业 周围人&#xff0c;生活不断升级 房子&#xff0c;车子&#xff0c;妻子…… 换了一茬又一茬 洋溢着自豪的表情 而我…

【kettle】pdi/data-integration 集成kerberos认证连接hdfs、hive或spark thriftserver

一、背景 kerberos认证是比较底层的认证&#xff0c;掌握好了用起来比较简单。 kettle完成kerberos认证后会存储认证信息在jvm中&#xff0c;之后直接连接hive就可以了无需提供额外的用户信息。 spark thriftserver本质就是通过hive jdbc协议连接并运行spark sql任务。 二、…

在职工程师该不该转嵌入式?如何转

是否在职工程师该不该转嵌入式&#xff0c;取决于自身情况和职业规划。 考虑职业发展方向&#xff1a;如果希望在嵌入式系统开发领域发展&#xff0c;那么转岗是合理的选择。嵌入式系统广泛应用于汽车、家电、医疗等领域&#xff0c;技术含量高&#xff0c;有广阔的职业发展空间…