C++中std::function和std::bind
1、可调用对象
可调用对象有一下几种定义:
- 是一个函数指针,参考 C++ 函数指针和函数类型;
- 是一个具有operator()成员函数的类的对象;
- 可被转换成函数指针的类对象;
- 一个类成员函数指针;
C++中可调用对象的虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++11中提供了std::function和std::bind统一了可调用对象的各种操作。
不同类型可能具有相同的调用形式,如:
// 普通函数
int add(int a, int b){return a+b;} // lambda表达式
auto mod = [](int a, int b){ return a % b;}// 函数对象类
struct divide{int operator()(int denominator, int divisor){return denominator/divisor;}
};
上述三种可调用对象虽然类型不同,但是共享了一种调用形式:
int(int ,int)
std::function就可以将上述类型保存起来,如下:
std::function<int(int ,int)> a = add;
std::function<int(int ,int)> b = mod ;
std::function<int(int ,int)> c = divide();
2、std::function
std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
定义格式:std::function<函数类型>。
std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数指针更加的灵活和便利。
3、std::bind
可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:
- 将可调用对象和其参数绑定成一个防函数;
- 只绑定部分参数,减少可调用对象传入的参数。
3.1 std::bind绑定普通函数
double my_divide (double x, double y) {return x/y;}
auto fn_half = std::bind (my_divide,_1,2);
std::cout << fn_half(10) << '\n'; // 5
- bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide,_1,2)等价于std::bind (&my_divide,_1,2);
- _1表示占位符,位于中,std::placeholders::_1;
3.2 std::bind绑定一个成员函数
struct Foo {void print_sum(int n1, int n2){std::cout << n1+n2 << '\n';}int data = 10;
};
int main()
{Foo foo;auto f = std::bind(&Foo::print_sum, &foo, 95, std::placeholders::_1);f(5); // 100
}
- bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
- 必须显示的指定&Foo::print_sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::print_sum前添加&;
- 使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;
3.3 绑定一个引用参数
默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中。但是,与lambda类似,有时对有些绑定的参数希望以引用的方式传递,或是要绑定参数的类型无法拷贝。
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std::placeholders;
using namespace std;ostream & print(ostream &os, const string& s, char c)
{os << s << c;return os;
}int main()
{vector<string> words{"helo", "world", "this", "is", "C++11"};ostringstream os;char c = ' ';for_each(words.begin(), words.end(), [&os, c](const string & s){os << s << c;} );cout << os.str() << endl;ostringstream os1;// ostream不能拷贝,若希望传递给bind一个对象,// 而不拷贝它,就必须使用标准库提供的ref函数for_each(words.begin(), words.end(),bind(print, ref(os1), _1, c));cout << os1.str() << endl;
}
4、指向成员函数的指针
通过下面的例子,熟悉一下指向成员函数的指针的定义方法。
#include <iostream>
struct Foo {int value;void f() { std::cout << "f(" << this->value << ")\n"; }void g() { std::cout << "g(" << this->value << ")\n"; }
};
void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) {(foo1->*fun)(); // call fun on the object foo1(foo2->*fun)(); // call fun on the object foo2
}
int main() {Foo foo1{1};Foo foo2{2};apply(&foo1, &foo2, &Foo::f);apply(&foo1, &foo2, &Foo::g);
}
- 成员函数指针的定义:void (Foo::*fun)(),调用是传递的实参: &Foo::f;
- fun为类成员函数指针,所以调用是要通过解引用的方式获取成员函数*fun,即(foo1->*fun)();
原文链接:https://www.jianshu.com/p/f191e88dcc80
C++中std::function和std::bind相关推荐
- std::function和std::bind
std::function和std::bind std::function 可调用对象 是一个函数指针 是一个具有operator()成员函数的类和对象 可被转换成函数指针的类对象: 一个类成员函数指 ...
- C++11 FAQ中文版:std::function 和 std::bind
std::function 和 std::bind 标准库函数bind()和function()定义于头文件中(该头文件还包括许多其他函数对象),用于处理函数及函数参数.bind()接受一个函数(或者 ...
- 可调用对象、std::function、std::bind
可调用对象.std::function.std::bind 仿函数functors function adapter bind(C++11) 函数适配器:bind2nd 仿函数适配器(mem_fun/ ...
- 【C++】C++11的std::function和std::bind用法详解
在设计回调函数的时候,无可避免地会接触到可回调对象.在C++11中,提供了std::function和std::bind两个方法来对可回调对象进行统一和封装. 可调用对象 C++中有如下几种可调用对象 ...
- std::function和std::bind用法
std::bind() std::bind 主要用于绑定生成目标函数,一般用于生成的回调函数,cocos的回退函数都是通过std::bind和std::function实现的.两个点要明白: 1.绑定 ...
- 【c++】24.std::function和std::bind详解
1. 可调用对象 查看全文 http://www.taodudu.cc/news/show-494578.html 相关文章: [c++]26.浅谈"事件驱动".select.po ...
- C++11中的std::function
文章转载自:http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码: std::function<void(EventKeyboard ...
- C++11 std::function, std::bind, std::ref, std::cref
C++11 std::function, std::bind, std::ref, std::cref 转自:http://www.jellythink.com/ std::function 看看这段 ...
- 【C++】char uchar string stringstream queue array vector set map std::function std::bind
文章目录 cout 防止使用科学计数法 一维数组的三种初始化方法 二维数组 vector作为参数的三种传参方式 vector 的 reserve resize set std::map std::pa ...
最新文章
- 博士申请 | 澳门大学汪澎洋助理教授招收机器学习方向全奖博士生
- angularjs http和ajax,AngularJS $ http和$ resource
- Hadoop机架感知
- 支付验证签名失败_验证码收不到,或许是验证码平台出了问题!
- 图片管理系统源码_「程序员分享」基于SpringBoot开发的天猫商城源码
- 编译在arm版本的Valgrind-转
- 规则引擎 drools_Drools的入门初探
- http抓包实践--(七)-fiddler弱网环境
- Retrofit完美封装
- 浏览器在线PDF预览取消下载按钮
- 计算机视觉硕士课程南京大学,南京大学计算机系研究生课程文库
- php开发h5游戏教程,HTML5游戏框架cnGameJS开发实录-实现动画原理
- 区块链、NFT与元宇宙中的稀缺性技术
- python人脸识别门禁_Python+Opencv+Tkinter指纹识别与人脸识别的门禁兼考勤(二)
- 32位机4G虚拟内存 64位机128G虚拟内存计算误区
- 文件上传漏洞初步解析(个人浅薄理解)
- 【C语言】数组的基本知识详细讲解(一维数组、二维数组、越界、存储.....
- 导出excel:下载模板时填充数据方法实现
- 手把手教您批量下载E宠商城多个商品图片并保存
- 【ijkplayer】介绍
热门文章
- python有哪些作用-python是什么 特点及功能
- python代码怎么运行-python代码如何运行
- 软件工程python就业方向-女生学习软件工程专业就业怎么样?
- python简单编程例子-python简单实例训练(21~30)
- linux查看python版本命令-linux 查看版本命令
- python对笔记本电脑的要求-学Python买什么笔记本电脑?
- python压缩包怎么安装-详解python解压压缩包的五种方法
- python语言自学-python语言学习笔记整理
- ROS调用本地摄像头数据并在rviz里显示
- 在导入graphsurgeon时报错:ImportError: cannot import name ‘NodeDef‘ from ‘tensorflow‘