c++之function和bind详解-SurfaceFlinger学习必备语法基础

news2024/11/25 18:27:03

背景

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
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
在这里插入图片描述

私聊作者+v(androidframework007)

七件套专题:在这里插入图片描述
点击这里 https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

视频:https://www.bilibili.com/video/BV1wc41117L4/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录 Leetcode860. 柠檬水找零

题目&#xff1a; 代码(首刷自解 2024年2月15日&#xff09;&#xff1a; class Solution { public:bool lemonadeChange(vector<int>& bills) {vector<int> leftchange(2,0);//leftchange[0]代表5元数量&#xff0c;1代表10for (int i 0; i < bills.size…

最小生成树(Kruskal算法及相关例题)

1.Kruskal算法概念以及基本思路 &#xff08;1&#xff09;概念&#xff1a; 克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。它的时间复杂度为O&#xff08;ElogE&#xff09;(E是图G的边的总数)&#xff0c;适合于求边稀疏的网的最小生成树 。 其基本思想是&#xff…

OS文件管理

文件管理 文件的属性 文件所包含的属性&#xff1a; 文件名&#xff1a;由创建文件的用户决定文件名&#xff0c;主要为了方便用户找到文件&#xff0c;同一目录下不允许有重名文件。标识符&#xff1a;一个系统内的各文件标识符唯一&#xff0c;对用户来说毫无可读性&#…

2.12:C语言测试题

1.段错误&#xff1a;申请堆区内存未返回&#xff0c;str指向NULL 2.段错误&#xff1a;局部变量&#xff0c;本函数结束&#xff0c;p也释放 3.越界访问&#xff0c;可能正常输出hello&#xff0c;可能报错 4.可能段错误&#xff0c;释放后&#xff0c;str未指向NULL&#x…

CentOS7.9+Kubernetes1.29.2+Docker25.0.3高可用集群二进制部署

CentOS7.9Kubernetes1.29.2Docker25.0.3高可用集群二进制部署 Kubernetes高可用集群&#xff08;Kubernetes1.29.2Docker25.0.3&#xff09;二进制部署二进制软件部署flannel v0.22.3网络&#xff0c;使用的etcd是版本3&#xff0c;与之前使用版本2不同。查看官方文档进行了解…

The method toList() is undefined for the type Stream

The method toList() is undefined for the type Stream &#xff08;JDK16&#xff09; default List<T> toList() { return (List<T>) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray()))); }

C语言strstr函数

简介 strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是&#xff0c;则该函数返回 str1字符串从 str2第一次出现的位置开始到 str1结尾的字符串&#xff1b;否则&#xff0c;返回NULL。 实验 #include "stdio.h" #include "string.h"c…

2.14:二维数组、非函数实现strcat、strcmp、strcpy、strlen

1.编程实现二维数组的杨辉三角 程序代码&#xff1a; 1 #include<stdio.h>2 #include<string.h>3 #include<stdlib.h>4 int main(int argc, const char *argv[])5 {6 int n;7 printf("please enter n:");8 scanf("%d",&…

2024/02/13

21 、C 22 、D 23、B 如果5先出栈那么1&#xff0c;2&#xff0c;3&#xff0c;4就已经入栈了&#xff0c;5出后4出&#xff0c;1要出栈必须先让3&#xff0c;2出栈&#xff0c;所以 不可能输出B 24、10&#xff0c;12&#xff0c;120 25、2&#xff0c;5 26、段错…

2024.02.12作业

1. 段错误 2. 段错误 3. hello 4. world 5. int a; int* a; int **a; int a[10]; int* a[10]; int(* a)[10]; int* a(int); int (*a[10])(int); 6. 6&#xff1b; 2&#xff1b; 2 7. 2 8. 2 9. b 10. a 11. a 12. c 13. b 14. c 15. a 16. c 17. b 18. a 19…

消息中间件特点

1.  消息中间件概念 消息中间件是消息传递的过程中保存消息的容器。 主要目的&#xff1a;提供路由并保证消息的传递&#xff1b;如果发送消息时接受者不可用&#xff0c;消息队列会保留信息&#xff0c;直到可以成功传递为止。 消息中间件保存消息也是有期限的。 2.  消息…

JVM工作原理与实战(三十八):JIT即时编译器原理

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、JIT即时编译器 二、HotSpot中的JIT编译器 三、JIT优化技术 1.方法内联 2.逃逸分析 四、JIT优化建议 总结 前言 JVM作为Java程序的运行环境&#xff0c;其负责解释和执行字节…

[计算机网络]---序列化和反序列化

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、再谈协议…

《VulnHub》GoldenEye:1

title: 《VulnHub》GoldenEye&#xff1a;1 date: 2024-02-16 14:53:49 updated: 2024-02-16 15:08:49 categories: WriteUp&#xff1a;Cyber-Range excerpt: 主机发现、目标信息扫描、源码 js 文件泄露敏感信息、hydra 爆破邮件服务&#xff08;pop3&#xff09;、邮件泄露敏…

成考怎么搜题答案?9个受欢迎的搜题分享了 #微信#职场发展

大学生应该养成良好的时间管理习惯&#xff0c;合理分配学习、休息和娱乐的时间&#xff0c;避免压力过大或时间浪费。 1.Forest专注森林 Forest是一款专注与时间管理应用。当你需要专注于学习或工作时&#xff0c;你可以在Forest应用中种植一棵虚拟树&#xff0c;设定一段时…

幻兽帕鲁——游戏优化【腾讯云服务器联机版本】

幻兽帕鲁8人以内联机&#xff0c;闭眼参加【腾讯云幻兽帕鲁专属游戏活动】4核16G12兆 购买腾讯云服务器后&#xff0c;游戏一键部署&#xff0c;联机流程参照这个博文 【10秒开服】雾锁王国全自动部署教程-CSDN博客 幻兽帕鲁——游戏优化 1.设置虚拟内存 第一步&#xff1a…

selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘

Selenium更新到 4.x版本后&#xff0c;以前的一些常用的代码的语法发生了改变 from selenium import webdriver browser webdriver.Chrome() browser.get(https://www.baidu.com) input browser.find_element_by_id(By.ID,kw) input.send_keys(Python)目标&#xff1a;希望通…

阿里云“BGP(多线)”和“BGP(多线)_精品”区别价格对比

阿里云香港等地域服务器的网络线路类型可以选择BGP&#xff08;多线&#xff09;和 BGP&#xff08;多线&#xff09;精品&#xff0c;普通的BGP多线和精品有什么区别&#xff1f;BGP&#xff08;多线&#xff09;适用于香港本地、香港和海外之间的互联网访问。使用BGP&#xf…

Linux:docker搭建redis集群(3主3从扩容缩容 哈希槽分配)

操作系统&#xff1a;centos7 docker-ce版本&#xff1a;24.0.7 1.准备redis镜像 我这里使用redis 6.0.8 镜像进行操作&#xff0c;如果你也需要镜像&#xff0c;在网络正常情况下直接使用 docker pull redis:6.0.8 即可进行下载&#xff0c;如果你没配置国内加速器&#x…

[java基础揉碎]数组 值拷贝和引用拷贝的赋值方式

目录 数组的介绍 为什么有数组 数组的三种使用方式 动态初始化: 静态初始化: 数组使用注意事项和细节 值拷贝和引用拷贝的赋值方式 数组反转: 数组拷贝: 数组的介绍 数组可以存放多个同一类型的数据。数组也是一种数据类型&#xff0c;是引用类型。 即&#xff1a;数组…