网站首页 > 博客文章 正文
背景
C++中的function和bind是为了更方便地进行函数对象的封装和调用而设计的,在SurfaceFlinger源码中也是有很多使用部分。比如分析Vsync相关源码时候有相关回调时候
在这里插入图片描述
可以看到这里的mRegistration就有个参数是 std::bind,怎么这里就可以进行回调呢?所以基于以上背景就需要学习今天的function和bind的知识才可以很轻松的分析对。function文档描述:
在这里插入图片描述
总结概况:
function是一个通用的函数对象容器,可以存储任意可调用对象(函数、函数指针、成员函数、成员变量、lambda表达式,任何function对象,比如一个类,定义了operator()),并提供了一致的接口来调用这些对象。通过function,可以将一个函数或函数对象作为参数传递给其他函数或存储在容器中,大大提高了灵活性。
template <class Ret, class... Args> class function<Ret(Args...)>;
参数解释:
Ret:代表调用function的返回结果的类型
Args:代表是参数的类型。
demo展示:
1、function存储函数指针方式
#include <iostream>
#include <functional>
int fl(int a)
{
std::cout << "a = " << a<< std::endl;
return a*2;
}
int main()
{
//直接可以接受函数指针的赋值
std::function<int(int)> f = fl;
int functionResult = f(1);
std::cout<<"function result = "<<functionResult<<std::endl;
int directResult = fl(1);
std::cout<<" fl result = "<<directResult<<std::endl; // 调用fl函数
return 0;
}
结果如下:
在这里插入图片描述
明显可以看到这里使用function对象调用方式和直接调用方法的方式都是一样的,结果都是2
2、存储类对象
在这里插入图片描述
可以看到这里的Add类对象也是可以作为一个作为一个function对象,但是这里需要注意Add类一定要进行重载operator这个方法
3、存储成员方法代码如下:
在这里插入图片描述
可以看出这里可以直接边类的成员方法赋值给function,不过这里function的Args里面第一个参数必须要求传递类对象。调用function时候第一个参数也是必须要是Add类的对象
4、lamada表达式情况
在这里插入图片描述
可以看出lamada表达式也是可以直接赋值给function对象5、类成员变量情况
在这里插入图片描述
可以看到类成员也可以直接通过function方式获取得到正确数据。bind学习文档:
https://legacy.cplusplus.com/reference/functional/bind/?kw=bind
在这里插入图片描述
总结bind作用:
bind是将函数和其参数进行绑定的工具,可以将一个函数和部分参数绑定在一起,生成一个新的函数对象,这个新的函数对象可以像原函数一样进行调用,但会自动填充绑定的参数。
核心参数补充:
第一个参数 fn
一个function对象,方法指针,或者是类成员变量
第二个参数
args所有参数的集合列表,要买具体的值,要么placeholders
返回值就是一个function的对象,当调用时候调用的就是fn这个方法体和带上传递的参数
重点强调一下最后两个:
If fn is a pointer to member, the first argument expected by the returned function is an object of the class *fn is a member (or a reference to it, or a pointer to it).
大概意思是如果fn是一个类成员相关的,那么第一个参数就需要是这个类的引用或者指针。
demo代码:
// bind example
#include <iostream> // std::cout
#include <functional> // std::bind
// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide (double x, double y) {return x/y;}
struct MyPair {
double a,b;
double multiply() {return a*b;}
};
int main () {
using namespace std::placeholders; // adds visibility of _1, _2, _3,...
// binding functions:
auto fn_five = std::bind (my_divide,10,2); // returns 10/2
std::cout << fn_five() << '\n'; // 5
auto fn_half = std::bind (my_divide,_1,2); // returns x/2
std::cout << fn_half(10) << '\n'; // 5
auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x
std::cout << fn_invert(10,2) << '\n'; // 0.2
auto fn_rounding = std::bind<int> (my_divide,_1,_2); // returns int(x/y)
std::cout << fn_rounding(10,3) << '\n'; // 3
MyPair ten_two {10,2};
//这里fn就是类成员方法,第一个参数就要求是这个类的对象,不过这里用的是空缺std::placeholders _1
// binding members:
auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
//这里调用时候传递了真正的对象ten_two
std::cout << bound_member_fn(ten_two) << '\n'; // 20
//这里fn就是类成员变量,第一个参数就要求是这个类的对象
auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
std::cout << bound_member_data() << '\n'; // 10
return 0;
}
std::placeholders _1,_2......就代表预制第1,2、、、个参数,后续真正调用function对象时候再传递进去
实战使用结合
在这里插入图片描述
可以看到这里的mRegistration构造方法第二个参数就是std::bind,即绑定方法,绑定是一个CallbackRepeater::callback的成员方法,而且有3个保留参数,即后续会传递进来的。
bind后就变成了function类型对象。那么这里的Registration第二个构造参数是啥呢?
在这里插入图片描述
这里的Callback实际就是地道的function对象
using Callback =
std::function<void(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime)>;
最后传递到了VSyncDispatchTimerQueueEntry中,在调用VSyncDispatchTimerQueueEntry的callback方法时候会调用上面的function类
在这里插入图片描述
本文章对应视频手把手教你学framework:
hal+perfetto+surfaceflinger
重大消息:Hal+perfetto-systrace+SurfaceFlinger合集新专题发布
在这里插入图片描述
私聊作者+v(androidframework007)
七件套专题:
在这里插入图片描述
点击这里
Android Framework开发rom实战合集课表/车载车机手机高级系统开发工程必会技能
视频:https://www.bilibili.com/video/BV1wc41117L4/
猜你喜欢
- 2025-01-15 kubernetes快速安装部署指南
- 2025-01-15 一文带你看懂vue基础语法、生命周期、指令、监听器、依赖注入
- 2025-01-15 美国工程合同中常见的招投标条款(中英文对照)
- 2025-01-15 JNI接口操作最佳实践(三)
- 2025-01-15 java基础都在这了,小主们拿去吧
- 2025-01-15 写作技巧——这些情况下,必须加连字符
- 2025-01-15 「云原生」k8s中volumeMounts.subPath的巧妙用法
- 2025-01-15 RmlUi:探索C++图形用户界面的璀璨明珠
- 2025-01-15 超级好用的配置文件解析器:minIni
- 2025-01-15 windows常见后门和Linux常见后门
你 发表评论:
欢迎- 366℃用AI Agent治理微服务的复杂性问题|QCon
- 358℃初次使用IntelliJ IDEA新建Maven项目
- 354℃手把手教程「JavaWeb」优雅的SpringMvc+Mybatis整合之路
- 351℃Maven技术方案最全手册(mavena)
- 348℃安利Touch Bar 专属应用,让闲置的Touch Bar活跃起来!
- 346℃InfoQ 2024 年趋势报告:架构篇(infoq+2024+年趋势报告:架构篇分析)
- 344℃IntelliJ IDEA 2018版本和2022版本创建 Maven 项目对比
- 342℃从头搭建 IntelliJ IDEA 环境(intellij idea建包)
- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)