C++学习笔记(三十五):c++ 函数指针及lambda表达式

本节介绍c++函数指针。在一些源码中经常能看到c++函数指针,但之前一直觉着这一块比较复杂,就一直没去仔细研究,终于有时间去仔细研究这一块内容了。

  • c风格的函数指针
  • 函数指针是指将一个函数赋值给一个变量的方法,可以将函数作为一个参数传递给另一个函数,简单的使用示例如下
  • #include <iostream>void PrintMessage()
    {std::cout << "Hello World!" << std::endl;
    }int main()
    {//一般情况下调用函数的方式//PrintMessage();//函数指针//取一个函数的地址赋值给一个变量auto function = PrintMessage;  //不加()//函数就是cpu指令,当编译完成代码后,函数处在二进制文件的某个地方//赋值给一个变量后可以向之前调用函数一样调用function();function(); //打印 "Hello World!"std::cin.get();
    }
  • 上述示例中是通过auto来接收,接下来看一下PrintMessage具体的返回值类型。
  • #include <iostream>void PrintMessage()
    {std::cout << "Hello World!" << std::endl;
    }int main()
    {//一般情况下调用函数的方式//PrintMessage();//函数指针//取一个函数的地址赋值给一个变量auto function = PrintMessage;  //不加()//函数就是cpu指令,当编译完成代码后,函数处在二进制文件的某个地方//赋值给一个变量后可以向之前调用函数一样调用function();function(); //打印 "Hello World!"//实际PrintMessage返回的类型是void(*function)()//实际的类型是void(*)(),最后一个括号里面的放的是函数的参数类型,function是我们给这个返回类型起的名字void(*pcop)();pcop = PrintMessage;pcop();//打印 "Hello World!"//上述的void(*pcop)()可以使用typedef,将别名写在如下位置,看起来可能有点奇怪,但确实是这样的typedef void(*testFunctionPoint)();testFunctionPoint heiheihei = PrintMessage;heiheihei();//打印 "Hello World!"std::cin.get();
    }
  • 接下来展示函数指针的函数包含参数的示例
  • #include <iostream>void PrintMessage(int a)
    {std::cout << "Hello World! " << a <<std::endl;
    }int main()
    {//一般情况下调用函数的方式//PrintMessage();//函数指针//取一个函数的地址赋值给一个变量auto function = PrintMessage;  //不加()//函数就是cpu指令,当编译完成代码后,函数处在二进制文件的某个地方//赋值给一个变量后可以向之前调用函数一样调用function(1);function(2); //打印 "Hello World!"//实际PrintMessage返回的类型是void(*function)()//实际的类型是void(*)(),最后一个括号里面的放的是函数的参数类型,function是我们给这个返回类型起的名字void(*pcop)(int);pcop = PrintMessage;pcop(5);//打印 "Hello World!"//上述的void(*pcop)()可以使用typedef,将别名写在如下位置,看起来可能有点奇怪,但确实是这样的typedef void(*testFunctionPoint)(int);testFunctionPoint heiheihei = PrintMessage;heiheihei(6);//打印 "Hello World!"std::cin.get();
    }
  • 上述描述的都是函数指针的原理,接下来大概展示函数指针的使用场景。
  • #include <iostream>
    #include <vector>
    void PrintValue(int value)
    {std::cout << value << std::endl;
    }void ForEach(const std::vector<int>& values, void(*func)(int))
    {for (int value:values){func(value);}
    }int main()
    {std::vector<int> values = {1,4,6,7,9};//创建一个函数,迭代遍历values中的所有元素,并将值进行打印ForEach(values, PrintValue);std::cin.get();
    }
  • c++lambda表达式
  • lambda表达式是指用一种匿名函数的创建函数,用这种方式创建函数不需要实际创建一个函数。只要有一个函数指针,都可以使用lambda。接下来通过代码展示lambda。
  • 上述的代码展示的是用lambda替换上节所讲述的PrintValue函数指针。()中传入的是lambda的{}中所需的参数,上述的func(value)实际上调用就是[](int value){std::cout << value << std::endl;}。
  • 接下来事例展示将一个函数传递给一个API,以便在未来的某个时间,可以为我们调用这个函数,现在不能掉用该函数,因为函数所需要的数据还为准备好,所以需要延迟调用。lambda可以很好的实现上述需求,代码实现如下:
  • []里面放的是lambda的捕获,当需要将外部的变量传入lambda{}中时用到。
  • #include <iostream>
    #include <vector>
    #include <functional>void ForEach(std::vector<int> vlaues ,const std::function<void(int)>& func)
    {for(int value:vlaues)func(value);
    }int main()
    {std::vector<int> values = {2,5,7,9,4};int a = 10;//想要在lambda中调用main函数的a变量,直接调用会报错//可以通过[=]值传递进行调用,也可以通过[&]传递进行调用//此时ForEach中的参数如果是原始函数指针就会报错,需要改成functionauto lambda = [=](int value){std::cout << value << a << std::endl;};ForEach(values, lambda);}
    
  • std::find_if,迭代器查找值
  • #include <iostream>
    #include <vector>
    #include <functional>
    #include <algorithm>void ForEach(std::vector<int> vlaues ,const std::function<void(int)>& func)
    {for(int value:vlaues)func(value);
    }int main()
    {std::vector<int> values = {2,5,7,9,4};//用find_if查找vector中第一个比3大的元素auto it = std::find_if(values.begin(),values.end(),[](int value){return value>3;} );std::cout << *it << std::endl;int a = 10;//想要在lambda中调用main函数的a变量,直接调用会报错//可以通过[=]值传递进行调用,也可以通过[&]传递进行调用//此时ForEach中的参数如果是原始函数指针就会报错,需要改成functionauto lambda = [=](int value){std::cout << value << a << std::endl;};ForEach(values, lambda);}
    

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

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

相关文章

linux命令--管道详解

关于linux命令的管道符的理解 管道&#xff1a;是进程之间的一种通信方式&#xff0c;主要适用的典型类型&#xff1a;父子进程 创建管道的函数c底层接口&#xff1a;int pipe(int f[2]) 返回的int类型&#xff0c;f[1]代表写&#xff0c;f[0]代表读 父进程使用fork函数创建副…

2024美赛数学建模思路 - 复盘:光照强度计算的优化模型

文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米&#xff0c;宽为12米&…

2024年1月11日 主题:非枪人生

2024年1月11日15:58:29 2024年1月11日15:35:13 2024年1月11日15:57:51 对物理进行大致预 2024年1月11日20:27:14 结论&#xff1a;不适合进行数据结构的训练和对电路的模拟感受 2024年1月11日20:28:32 今天也平静的结束了 不需要键盘的支持也就这么结束了我也不知道…

怎么处理网站的一些安全风险

随时互联网的持续发展&#xff0c;数字化转型步伐不断加快&#xff0c;社会各行业都走进了信息化、数字化。但与此同时&#xff0c;网络发展带来了许多风险&#xff0c;各行业面临着日益复杂的数据安全和网络安全威胁。其中&#xff0c;网站的安全风险持续增长&#xff0c;是各…

C++ Primer 6.2参数传递 知识点+练习题

C Primer 6.2参数传递 知识点练习题 指针形参使用引用拷贝Const 形参实参尽量使用常量引用数组形参数组引用形参传递多维数组向main函数传参数含有可变形参的函数练习题待更新 指针形参 void reset(int *p) {*p0;//p指向的整型对象变为0p0;//只是对形参改变p&#xff0c;使其为…

详解如何撰写一个基础的技术交底书

大家好,我是英子老师。作为一名知识产权专家,深耕于专利行业十余年,具有丰富的专利工作经验:曾在大型专利代理机构从事专利代理工作、专利质检工作(抽查代理机构的专利代理人的撰写质量并评分);之后在知名上市企业、行业龙头企业担任高级专利工程师的职位,主要工作内容…

Linux ----冯诺依曼体系结构与操作系统

目录 前言 一、冯诺依曼体系结构 二、为什么选择冯诺依曼体系结构&#xff1f; 三、使用冯诺依曼结构解释问题 问题1&#xff1a; 问题2: 四、操作系统 1.操作系统是什么 2.为什么需要操作系统 3.操作系统怎样管理的 4.如何给用户提供良好环境 五、我们是怎样调用系…

2023年全国职业院校技能大赛软件测试赛题—单元测试卷④

任务二 单元测试 一、任务要求 题目1&#xff1a;根据下列流程图编写程序实现相应分析处理并显示结果。返回结果“ax&#xff1a;”&#xff08;x为2、3或4&#xff09;&#xff1b;其中变量x、y均须为整型。编写程序代码&#xff0c;使用JUnit框架编写测试类对编写的程序代码…

第19课 在Android环境中使用FFmpeg和openCV进行开发的一般步骤

在上节课&#xff0c;根据模板文件我们对在Android环境中使用FFmpeg和openCV进行开发有了一个初步的体验&#xff0c;这节课&#xff0c;我们来具体看一下其工作流程。 1.程序的入口 与VS2013程序开发类似&#xff0c;Android程序开发也有一个入口&#xff0c;在这个模板中&a…

图像识别与计算机视觉有什么区别?

图像识别和计算机视觉在很多方面存在差异&#xff0c;这些差异主要体现在以下几个方面&#xff1a; 1. 研究范围 图像识别是计算机视觉领域的一个子集。计算机视觉不仅包括图像识别&#xff0c;还涵盖了更广泛的内容&#xff0c;如场景理解、目标跟踪、分割、识别和解释等。简而…

SQL-分组查询

目录 DQL-分组查询 分组查询注意事项&#xff1a; DQL- 排序查询 &#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &…

Mysql——索引相关的数据结构

索引 引入 我们知道&#xff0c;数据库查询是数据库的最主要功能之一。我们都希望查询数据的速度能尽可能的快&#xff0c;因此数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法当然是顺序查找&#xff08;linear search&#xff09;&#xff0c;这种复杂度为…