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.mzph.cn/news/613888.shtml

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

相关文章

Vercel配置自定义域名

首先你需要有一个域名 1.点击部署的项目设置 2.找到Domains 3.输入自己的域名 点击添加之后按要求去域名服务商添加解析即可 4.显示下面内容就设置完成了&#xff0c;

Ubuntu下wifi 无线网络的配置

先说结论&#xff1a;终端模式下没有找到无脑安装的方法&#xff0c;也就是需要修改配置文件。 首先安装相关库 sudo apt install network-manager wpasupplicant wireless-tools然后到/etc/netplan目录下&#xff0c;配置50-cloud-init.yaml文件。如果没有这个文件&#xff0…

激活/注册navicat15

一、获取软件 链接&#xff1a;https://pan.baidu.com/s/1F_tiLuLvVFMEz8pDfIvDjw?pwdjjfj 提取码&#xff1a;jjfj 二、安装 安装的过程我就不放了&#xff0c;重点如下 安装完不要打开软件&#xff01; 安装完不要打开软件&#xff01; 安装完不要打开软件&#xff01;…

强化学习求解TSP(三):Qlearning求解旅行商问题TSP(提供Python代码)

一、Qlearning简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于奖励的决策问题。它是一种无模型的学习方法&#xff0c;通过与环境的交互来学习最优策略。Q-learning的核心思想是通过学习一个Q值函数来指导决策&#xff0c;该函数表示在给定状态下采取某个动作所获…

【响应式编程】前置知识和相关技术的总结

前置知识 这些概念都与响应式编程密切相关。&#x1f98c; 1. 并发和多线程编程&#xff1a;响应式编程需要处理并发性&#xff0c;它允许多个操作独立地并行执行。这使得应用程序可以在不同的线程、进程或设备上处理多个事件。 2. 事件驱动编程&#xff1a;响应式编程是一种…

回首24考研历程,那些无法忘却的收获

文章目录 毅力与坚持&#x1f44d;知识的力量&#x1f9d0;心态的历练&#x1f913;友谊与互助( •̀ ω •́ )y未来的启示(●◡●) 在这个充满希望与挑战的时刻&#xff0c;我想与你们分享一段关于2023这一年特别的经历——考研之路。这段旅程既有磨砺的痛楚&#xff0c;也有…

小程序基础学习(事件处理)

概述&#xff1a;点击某一个标题&#xff0c;使标题选中增加不同颜色。 <!--pages/four/four.wxml--> <navigation-bar title"牧原" back"{{false}}" color"black" background"#FFF"></navigation-bar> <view c…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷⑩

2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷10 目录 需要竞赛软件包环境以及备赛资源可私信博主&#xff01;&#xff01;&#xff01; 2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷10 模块…

RT-Thread: ulog 日志 讲解和使用

说明&#xff1a;记录 RT-Thread: ulog 日志功能和使用流程。 官网资料链接&#xff1a; https://docs.rt-thread.org/#/rt-thread-version/rt-thread-standard/programming-manual/ulog/ulog 1.ulog 简介 日志的定义&#xff1a;日志是将软件运行的状态、过程等信息&#x…

海外市场调研为什么要用独享静态代理IP?

独享静态IP在海外市场调研中扮演着至关重要的角色&#xff0c;提供了一系列无可比拟的优势。独享静态代理IP的稳定性和可靠性对于长期的市场调研至关重要&#xff0c;它保证了连接的持续性和数据的准确性。通过这些方面的综合优势&#xff0c;独享静态代理IP成为海外市场调研中…

工业智能网关:HiWoo Box远程采集设备数据

工业智能网关&#xff1a;HiWoo Box远程采集设备数据 在工业4.0和智能制造的浪潮下&#xff0c;工业互联网已成为推动产业升级、提升生产效率的关键。而在这其中&#xff0c;工业智能网关扮演着至关重要的角色。今天&#xff0c;我们就来深入探讨一下工业智能网关。 一、什么…

用Linux的视角来理解缓冲区概念

缓冲区的认识 缓冲区&#xff08;buffer&#xff09;是存储数据的临时存储区域。当我们用C语言向文件中写入数据时&#xff0c;数据并不会直接的写到文件中&#xff0c;中途还经过了缓冲区&#xff0c;而我们需要对缓冲区的数据进行刷新&#xff0c;那么数据才算写到文件当中。…

C++中ios::in, ios::out, ios::trunc使用

目录 一&#xff0c;ios::in 二&#xff0c;ios::out 三&#xff0c;ios::trunc 四&#xff0c;组合使用 在C中&#xff0c;ios::in和ios::out是iostream库中定义的一些标志&#xff0c;用于控制文件流对象&#xff08;如fstream、ifstream和ofstream&#xff09;的行为。…

Java获取IP地址及对应的归属地

目录 前言 一、获取访问的IP地址 二、通过IP地址获取对应的归属地 2.1 Ip2region 2.1.1 高达 99.9 % 的查询准确率 2.1.2 Ip2region V2.0 特性 2.1.3 多语言以及查询客户端的支持 2.2 Ip2region xdb Java 查询客户端实现 2.2.1 引入 Maven 仓库 2.2.2 ip2region.xdb …

【.NET Core】可为null类型详解

【.NET Core】可为null类型详解 文章目录 【.NET Core】可为null类型详解一、概述二、可为空的值类型2.1 声明和赋值2.2 检查可为空值类型2.3 基础类型与可为空的值类型互换2.4 可为空的值类型装箱和取消装箱2.5 如何确定可为空的值类型 三、可为 null 的引用类型 一、概述 nu…

用通俗易懂的方式讲解:在 Langchain 中建立一个多模态的 RAG 管道

写在前面 语言模型的出现彻底改变了我们从文件中提取信息的方式。然而&#xff0c;我们知道图片&#xff0c;通常是图表和表格&#xff0c;经常包含关键信息&#xff0c;但基于文本的语言模型无法处理媒体文件。 例如&#xff0c;我们以前只能使用 PDF 文件中的文本来查找答案…

C#编程-实现线程声明周期

实现线程声明周期 当System.Threading.Thread类的对象被创建的时候,线程的生命周期开始。线程的生命周期在完成任务时结束。在线程的生命周期中有各种状态。这些状态是: 未启动状态可运行状态不可运行状态死亡状态下图显示了线程的各种状态和引起线程从一个状态变为另一个状…

欢乐的周末 - 华为OD统一考试

OD统一考试 题解: Java / Python / C++ 题目描述 小华和小为是很要好的朋友,他们约定周末一起吃饭。 通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达)。求小华和小为都能到达的聚餐地点有多少个? 输入描述 第一行输入m和n,m代表…

C练习——递归求第n个人年龄

题目&#xff1a; 有n个人坐在一起&#xff0c;第n个人比第n-1个人大2岁&#xff0c;第n-1个人比第n-2个人大2岁&#xff0c;以此类推&#xff0c;……&#xff0c;第1个人是10岁。请问第n个人年龄多大&#xff1f; 解析&#xff1a; 简单循环也能求解 但按题意要求递归求解…

Spark SQL进阶

DataFrame详解 清洗相关API 去重API 删除空缺值的API 替换缺失值的API from pyspark import SparkConf, SparkContext import os from pyspark.sql import SparkSession# 绑定指定的Python解释器 os.environ[SPARK_HOME] /export/server/spark os.environ[PYSPARK_PYTHON]…