一文教会你lambda表达式

引言

在现代编程中,Lambda表达式(也称为匿名函数或闭包)已经成为了一种非常流行的编程范式。它允许我们定义简短、一次性的函数对象,而无需显式地定义它们。在C++11及之后的版本中,Lambda表达式得到了官方的支持,为C++程序员带来了极大的便利。本文将详细解释Lambda表达式的概念、语法以及如何使用它们。

Lambda表达式的概念

Lambda表达式是一种匿名函数,即没有具体名称的函数。它可以捕获其所在作用域的变量,并在需要时执行特定的操作。Lambda表达式通常用于实现回调函数、并行计算、排序算法等场景。

Lambda表达式的语法

Lambda表达式的语法相对简单,其基本形式如下:

[capture](parameters) -> return_type { body }
  • [capture]:捕获子句,用于指定Lambda表达式可以访问的外部变量及其访问方式(值捕获或引用捕获)。
  • (parameters):参数列表,与普通函数的参数列表类似,用于指定Lambda表达式的输入参数。
  • -> return_type:返回类型说明符,用于指定Lambda表达式的返回类型。如果Lambda表达式的返回类型可以由编译器自动推导,则可以省略该部分。
  • { body }:Lambda表达式的主体,即函数体,包含要执行的代码。

Lambda表达式的使用

 下面我们将通过几个示例来演示Lambda表达式的使用。

示例1:无参数、无返回值的Lambda表达式

 
#include <iostream> int main() { auto lambda = [] { std::cout << "Hello, Lambda!" << std::endl; }; lambda(); // 调用Lambda表达式 return 0; }

在这个示例中,我们定义了一个无参数、无返回值的Lambda表达式,并将其赋值给lambda变量。然后,我们像调用普通函数一样调用lambda()

示例2:有参数、有返回值的Lambda表达式

#include <iostream> 
#include <vector> 
#include <algorithm> int main() { 
std::vector<int> numbers = {1, 2, 3, 4, 5}; 
std::sort(numbers.begin(), numbers.end(), [](int a, int b) { 
return a < b; // 定义了比较函数 
}); 
// 输出排序后的结果 
for (int num : numbers) { 
std::cout << num << " "; 
} 
std::cout << std::endl; 
return 0; 
}

在这个示例中,我们使用了一个Lambda表达式作为std::sort函数的第三个参数。这个Lambda表达式接受两个整数参数ab,并返回一个布尔值,用于指示a是否小于b。通过这种方式,我们告诉std::sort函数如何对整数进行排序。

示例3 -- 对回调函数使用lambda 表达式

原程序

#include<iostream>using namespace std;bool compare(int a,int b){ // 比较前者是否大于后者return  a>b;
}
// 回调函数 -- 获取两数的最大值
int getMax(int a,int b,bool(*compare)(int a,int b))
{if(compare(a,b)){return a;}elsereturn b;}int main()
{int a = 55,b=99;bool (*funcp)(int ,int ) = compare;cout<<getMax(a,b,funcp)<<endl;return 0;
}

改进为 lambda 表达式


// 接下来- 我们 可以吧compare 这个函数 改进为 lambda 表达式:


 

int main()
{int a = 555,b=99;//bool (*funcp)(int ,int ) = compare;cout<<getMax(a,b,  [](int a,int b) ->bool {return a>b;})<<endl;return 0;
}


在这个例子中:
getMax 函数接受两个整数 a 和 b ,以及一个比较函数 compare 。这个比较函数是一个指向函数
的指针,它接受两个整数并返回一个布尔值。
在 main 函数中,我们调用 getMax ,并直接在调用点定义了一个匿名的 lambda 函数。这个
lambda 函数接受两个整数并返回一个表示第一个整数是否大于第二个整数的布尔值。
这个 lambda 函数在 getMax 中被用作比较两个数的逻辑。根据 lambda 函数的返回值, getMax
返回较大的数。
这个例子展示了如何直接在函数调用中使用匿名 lambda 函数,使代码更加简洁和直接。这种方法在需
要临时函数逻辑的场合非常有用,尤其是在比较、条件检查或小型回调中。
在 Lambda 表达式中,参数捕获是指 Lambda 表达式从其定义的上下文中捕获变量的能力。这使得
Lambda 可以使用并操作在其外部定义的变量。捕获可以按值(拷贝)或按引用进行。
让我们通过一个简单的示例来展示带参数捕获的 Lambda 表达式。

Lambda  表达式的捕获列表

三种捕获方式

第一种捕获方式: [x,y] --> 指定变量捕获

     auto add=[x,y]()->int{return  x +y;}


第二种捕获方式: --> = 一键全部

    auto mul=[=]()->int{ // =  捕获上面的所有变量//x++;   //这种方式的捕获是没法修改变量的值 --> 可读 只能使用//y = 10;return  x*y*z;};


第三种捕获方式: --> & 一键全部,并且能拿到他们的地址,进行修改


 

  auto modifAndMul=[&]()->int{ // =  捕获上面的所有变量y = 10; //可读可写return  x*y*z;};

全部整合实例代码;

#include <iostream>
using namespace  std;int main()
{int x = 10;int y = 30;auto add=[x,y]()->int{//x++;   //这种方式的捕获是没法修改变量的值 --> 可读 只能使用//y = 10;return  x +y;};cout << add()<<endl;int z = 5;auto mul=[=]()->int{ // =  捕获上面的所有变量//x++;   //这种方式的捕获是没法修改变量的值 --> 可读 只能使用//y = 10;return  x*y*z;};int c=66; // 下面的定义的变量 = 就捕获不到 --> 但是不了的 初始化一般都设置在函数的开头cout << mul()<<endl;//  用引用的方式来进行捕获,类似指针,进行地址访问auto modifAndMul=[&]()->int{ // =  捕获上面的所有变量y = 10; //可读可写return  x*y*z;};cout << modifAndMul()<<endl<<"y = "<<y<<endl;;return 0;
}

输出结果:

说明

在这个例子中:
第一个 Lambda 表达式 sum 按值捕获了 x 和 y (即它们的副本)。这意味着 sum 内的 x 和 y
是在 Lambda 定义时的值的拷贝。
第二个 Lambda 表达式 multiply 使用 [=] 捕获列表,这表示它按值捕获所有外部变量。
第三个 Lambda 表达式 modifyAndSum 使用 [&] 捕获列表,这表示它按引用捕获所有外部变量。
因此,它可以修改 x 和 y 的原始值。
这个示例展示了如何使用不同类型的捕获列表(按值和按引用)来控制 Lambda 表达式对外部变量的访问和修改。按值捕获是安全的,但不允许修改原始变量,而按引用捕获允许修改原始变量,但需要注意引用的有效性和生命周期问题。

请注意,虽然 Lambda 函数和内联函数在某些方面有相似之处,如它们都可以被编译器优化以减少调用开销,但它们在设计和用途上有明显的不同。Lambda 函数的核心优势在于它们的匿名性和对外部变量的捕获能力,而内联函数则主要关注于提高小型函数的性能。

内联函数

概念


内联函数(Inline Function)是C++中一种特殊的函数,其定义直接在每个调用点展开。这意味着编译器会尝试将函数调用替换为函数本身的代码,这样可以减少函数调用的开销,尤其是在小型函数中。


特点


1. 减少函数调用开销:内联函数通常用于优化小型、频繁调用的函数,因为它避免了函数调用的常规开销(如参数传递、栈操作等)。


2. 编译器决策:即使函数被声明为内联,编译器也可能决定不进行内联,特别是对于复杂或递归函数。


3. 适用于小型函数:通常只有简单的、执行时间短的函数适合做内联。

4. 定义在每个使用点:内联函数的定义(而非仅仅是声明)必须对每个使用它的文件都可见,通常意味着将内联函数定义在头文件中。


使用方法


通过在函数声明前添加关键字 inline 来指示编译器该函数适合内联:

inline int max(int x, int y) {
return x > y ? x : y;
}

示例

#include <iostream>
inline int add(int a, int b) {
return a + b;
}
int main() {
int result = add(5, 3); // 编译器可能会将此替换为:int result = 5 + 3;
std::cout << "Result: " << result << std::endl;
return 0;
}

在这个示例中,函数 add 被定义为内联函数。当它被调用时,编译器可能会将函数调用替换为函数体内的代码。

注意事项


过度使用的风险:不应滥用内联函数,因为这可能会增加最终程序的大小(代码膨胀)。对于大型函数或递归函数,内联可能导致性能下降。


编译器的决定:最终是否将函数内联是由编译器决定的,即使函数被标记为 inline 。


适用场景:最适合内联的是小型函数和在性能要求高的代码中频繁调用的函数。


内联函数是一种用于优化程序性能的工具,但需要合理使用,以确保代码的可维护性和性能的平衡。

 Lambda 函数和内联函数在 C++ 中的相似之处和区别:

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

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

相关文章

梦幻西游12门派复古怀旧 单机版 安装简单,云盘下载哦

做游戏开发的朋友&#xff0c;可以多参考里面的设计思想&#xff0c;真的不错。 梦幻西游12门派复古怀旧 单机版 安装简单&#xff0c;云盘下载哦 游戏大小&#xff1a; 支持系统&#xff1a;win7、win10 64位 特色&#xff1a;简化安装&#xff0c;非常容易。 重新整盒高…

MLIP-3主动机器学习方法探索

INPUT文件 此文件中包含15个文件&#xff0c;逐个分析他们的功能 Cu_1620.data&#xff1a;LAMMPS的初始文件需要搭配in文件一起使用 README.md&#xff1a;解释文件&#xff0c;解释各个文件的功能以及操作流程 VASP/&#xff1a;文件夹 auto.sh&#xff1a;执行最主要的文件…

Ubuntu下halcon软件的下载安装

由于工作需求&#xff0c;点云配准需要使用halcon进行实现&#xff0c;并且将该功能放入QT界面中 1.下载halcon 进入halcon官网进行下载 官网链接&#xff1a;https://www.mvtec.com/products/halcon/ 注意&#xff1a;要注册登陆之后才能进行下载 接着点击Downloads->H…

MouseBoost PRO mac中文激活版:专业鼠标助手

MouseBoost PRO mac鼠标性能优化软件&#xff0c;以其强大的功能和智能化的操作&#xff0c;助您轻松驾驭鼠标&#xff0c;提高工作效率。 MouseBoost PRO支持自定义快捷键设置&#xff0c;让您轻松实现快速切换应用程序、打开特定文件、调节音量大小等操作。自动识别窗口功能则…

达梦 定义水平分区表

水平分区包括范围分区、哈希分区和列表分区三种。水平分区表的创建需要通过 <PARTITION 子句>指定。 范围&#xff08;RANGE&#xff09;分区&#xff0c;按照分区列的数据范围&#xff0c;确定实际数据存放位置的划分方式。 列表&#xff08;LIST&#xff09;分区&a…

240多道!Go开发岗位面试题合集(含答案)

随着今年互联网寒潮环境的影响&#xff0c;找工作的人也将达到顶峰&#xff0c;今天给大家分享一份《Go开发工程师超高频面试真题》&#xff0c;一共有240多道面试真题&#xff0c;希望能够帮助大家在面试中&#xff0c;少走一些弯路、更快拿到offer&#xff01; 内容展示 GO 基…

Dreamweaver 2021 for Mac 激活版:网页设计工具

在追求卓越的网页设计道路上&#xff0c;Dreamweaver 2021 for Mac无疑是您的梦幻之选。这款专为Mac用户打造的网页设计工具&#xff0c;集强大的功能与出色的用户体验于一身。 Dreamweaver 2021支持多种网页标准和技术&#xff0c;让您能够轻松创建符合现代网页设计的作品。其…

论文精度-Attention Is All You Need

文章目录 论文精读-Transformer(Attention is All You Need)1.Transformer 整体结构2. Transformer 的输入2.1 单词 Embedding2.2 位置 Embedding3. Self-Attention(自注意力机制)3.1 Self-Attention 结构3.2 Q, K, V 的计算3.3 Self-Attention 的输出3.4 Multi-Head Attent…

[Algorithm][BFS][拓扑排序][课程表][课程表Ⅱ][火星词典] + BFS解决拓扑排序原理 详细讲解

目录 0.原理讲解1.有向无环图2.AOV网3.拓扑排序4.实现拓扑排序5.如何建图&#xff1f; 1.课程表1.题目链接2.算法原理详解3.代码实现 2.课程表 II1.题目链接2.算法原理详解3.代码实现 3.火星词典1.题目链接2.算法原理详解3.代码实现 0.原理讲解 1.有向无环图 有向无环图&#…

基于Django图像识别系统毕业设计(付源码)

前言&#xff1a;Django是一个由Python编写的具有完整架站能力的开源Web框架&#xff0c;Django本身基于MVC模型&#xff0c;即Model&#xff08;模型&#xff09;View&#xff08;视图&#xff09; Controller&#xff08;控制器&#xff09;设计模式&#xff0c;因此天然具有…

AR技术的那些事

什么是AR技术&#xff1f; AR技术&#xff0c;全称为增强现实技术&#xff08;Augmented Reality&#xff09;&#xff0c;是一种将虚拟信息叠加到现实世界中的技术。通过AR技术&#xff0c;用户可以通过手机、平板电脑、AR眼镜等设备&#xff0c;将虚拟的数字内容&#xff08;…

【抽样调查】分层抽样上

碎碎念&#xff1a;在大一大二时听课有的时候会发现听不太懂&#xff0c;那时候只觉得是我自己的基础不好的原因&#xff0c;但现在我发现“听不懂”是能够针对性解决的。比如抽样调查这门课&#xff0c;分析过后我发现我听不懂的原因之一是“没有框架”&#xff0c;一大堆知识…

【使用ChatGPT的API之前】OpenAI API提供的可用模型

文章目录 一. ChatGPT基本概念二. OpenAI API提供的可用模型1. InstructGPT2. ChatGPT3. GPT-4 三. 在OpenAI Playground中使用GPT模型-ing 在使用GPT-4和ChatGPT的API集成到Python应用程序之前&#xff0c;我们先了解ChatGPT的基本概念&#xff0c;与OpenAI API提供的可用模型…

情感分类学习笔记(1)

文本情感分类&#xff08;二&#xff09;&#xff1a;深度学习模型 - 科学空间|Scientific Spaces 一、代码理解 cw lambda x: list(jieba.cut(x)) #定义分词函数 您给出的代码定义了一个使用 jieba 分词库的分词函数。jieba 是一个用于中文分词的 Python 库。该函数 cw 是…

03_led_horse_run_v0 跑马灯

03_led_horse_run_v0 在Verilog中实现跑马灯通常涉及到使用一个计数器来控制LED灯的亮灭顺序。 跑马灯是一种常见的电子显示方式&#xff0c;它通过控制多个LED灯的顺序点亮&#xff0c;形成一种动态的视觉效果&#xff0c;看起来就像灯在“跑”一样。 知识点&#xff1a; 移…

FTTR介绍

概念 FTTR&#xff08;Fiber to The Room&#xff09;是一种新型的光纤接入技术&#xff0c;它将光纤信号传输到室内的一个通信网络方案。在FTTR网络中&#xff0c;光纤到达建筑物内的分配盒后&#xff0c;通过铜缆或其他传输介质进入室内各个房间&#xff0c;为用户提供网络服…

Java面试八股文(SpringCloud篇)

****************************************************

前端双语实现方案(VUE版)

一、封装一个lib包 结构如下 en.js use strict;exports.__esModule true; exports.default {sp: {input: {amountError: Incorrect amount format},table: {total: Total:,selected: Selected:,tableNoData: No data,tableNoDataSubtext: Tip: Suggest to recheck your fil…

springboot利用Redis的Geo数据类型,获取附近店铺的坐标位置和距离列表

文章目录 GEO介绍GEO命令行应用添加地理坐标位置获取指定单位半径的全部地理位置列表springboot 的实际应用 GEO介绍 在Redis 3.2版本中&#xff0c;新增了一种数据类型&#xff1a;GEO&#xff0c;它主要用于存储地理位置信息&#xff0c;并对存储的信息进行操作。 GEO实际上…

整理好了!2024年最常见 100 道 Java基础面试题(三十七)

上一篇地址&#xff1a;整理好了&#xff01;2024年最常见 100 道 Java基础面试题&#xff08;三十六&#xff09;-CSDN博客 七十三、抽象类是否可以继承具体类&#xff1f; 在Java中&#xff0c;抽象类&#xff08;abstract class&#xff09;可以继承自具体类&#xff08;c…