C++中lambda表达式的使用及注意事项

在C++中一共有四种可调用对象,分别是函数,函数指针,仿函数,和lambda表达式,本文将从lambda表达式的定义形式开始,到lambda表达式的使用场景,向你讲述lambda的使用及注意事项。

lambda表达式的定义形式

[capture list] (parameter list)->return type{function body}

从上面的表达式我们可以看出lambda表达式主要分为四部分

  1. 捕获列表:定义了lambda表达式可以从创建它的作用域中捕获哪些变量以及如何捕获(值捕获或引用捕获)。
  2. 参数列表:和普通函数一样,用于定义输入参数。
  3. 返回类型:可选项,如果省略,编译器会根据函数体中的返回语句自动推导返回类型。
  4. 函数体:包含实现lambda功能的代码块。

其中参数列表、返回类型、函数体都可以类似于普通的函数去理解,似乎lambda就是一个普通的匿名函数(虽然它确实是)。但是捕获列表具体是什么,似乎还是有些晦涩。

捕获列表

捕获列表的种类主要有:

  • [] 不捕获任何外部变量。
  • [x, &y] 按值捕获变量x,按引用捕获变量y
  • [=] 按值捕获所有外部变量。
  • [&] 按引用捕获所有外部变量。
  • [this] 捕获当前类的this指针,使得可以访问类的成员变量和成员函数。

从上面的种类来看上捕获列表在lambda表达式中的作用有点类似于全局变量在普通函数中的作用,但两者之间存在一些关键的区别和限制:

捕获列表的特点

  1. 有限作用域:lambda的捕获列表仅能捕获定义lambda的那个作用域内的变量。这与全局变量不同,后者在整个程序中都是可见的。
  2. 显式声明:你必须在捕获列表中显式指定lambda可以访问哪些变量以及如何访问(按值或按引用)。这增加了代码的可读性和可维护性,因为你可以一眼看出lambda依赖哪些外部变量。
  3. 选择性捕获:可以选择仅捕获需要的变量,而不是自动拥有访问所有外部变量的权限。这有助于限制lambda内部的操作,防止意外修改不应该修改的变量。
  4. 不同捕获方式:可以按值捕获,也可以按引用捕获。按值捕获可以防止原始数据被意外修改,按引用捕获则可以减少数据复制的开销,并允许lambda修改原始数据。

相比全局变量的优势

  • 减少依赖和副作用:使用捕获列表可以明确地限定lambda表达式的作用域和依赖,避免了全局变量可能带来的不可预测的侧面影响。
  • 提高代码的封装性和安全性:通过限定访问特定变量的权限,你可以更安全地管理代码中的数据流和状态变化,减少bug的产生。
  • 增强代码的模块性:lambda表达式通常用于实现具体的、局部的功能,与全局变量相比,这种方式可以更好地封装功能,便于功能间的解耦和重用。

总结来说,虽然捕获列表在某种意义上与全局变量具有可比性,特别是在变量的可访问性方面,但lambda表达式通过其独特的设计,提供了更大的灵活性和更强的安全保障,使得代码更加健壮和易于维护。

lambda表达式的使用

在lambda表达式中,我们可以忽略参数列表和返回类型,但是必须永远包含捕捉列表和函数体。

auto f=[]{return 1;};

在这个例子中我们定义了一个可调用对象f,它不接受参数返回1;它的调用方式和普通函数一样,

std::cout<<f()<<std::endl;

lambda的使用场景

1. STL算法

Lambda表达式常用于标准模板库(STL)的算法中,作为自定义操作的参数。例如,使用std::sort()std::for_each()std::transform()等算法时,可以用lambda表达式来定义比较函数或操作函数。

cppCopy codestd::vector<int> v = {4, 1, 3, 5, 2};
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); // 降序排序
std::for_each(v.begin(), v.end(), [](int x) { std::cout << x << " "; }); // 输出

2. 作为回调函数

在需要传递回调函数的场合,lambda表达式提供了一种快捷方便的方式来实现。比如在GUI编程或事件驱动编程中,可以用lambda来响应事件,如按钮点击等。

cpp
Copy code
button.onClick([](){ std::cout << "Button clicked!" << std::endl; });

3. 封装代码块

Lambda表达式可以封装一段只在特定上下文中运行的代码,使得整个代码结构更清晰。例如,你可能需要多次执行某个复杂的计算或操作,通过将这些操作封装在一个lambda中,可以简化代码的重用。

cppCopy codeauto complexOperation = []() {// 执行复杂操作std::cout << "Operation done!" << std::endl;
};
complexOperation(); // 调用

4. 延迟计算

Lambda表达式常用于实现延迟计算,尤其是在函数式编程范式中。这包括延迟执行某些操作直到真正需要它们的结果为止,有助于优化性能和资源使用。

cppCopy codeauto lazyValue = [](int x) { return x * x; };
std::cout << "Computed value: " << lazyValue(5); // 只在需要时计算

5. 替代函数对象

在C++11之前,通常使用函数对象(functors)来实现类似的功能。Lambda表达式提供了一种更加简洁和直观的方式来替代函数对象,特别是在需要传递简短的操作时。

cppCopy codestd::vector<int> numbers = {1, 2, 3, 4, 5};
std::transform(numbers.begin(), numbers.end(), numbers.begin(), [](int n) { return n * n; });

6. 简化异步编程

在使用异步编程模式,如C++11中的std::async或其他并发编程工具时,lambda表达式可以作为简单的任务封装方式使用,以便在后台线程中执行。

cppCopy codeauto future = std::async(std::launch::async, []() {return fetchDataFromDB("query"); // 假设的数据库查询函数
});

通过这些示例和解释,可以看出lambda表达式如何在各种不同的场景下提供代码封装、简化和性能优化的优势。随着C++标准的不断发展,lambda表达式的使用场景和功能也在持续扩展。

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

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

相关文章

Java中的ThreadLocal为什么使用弱引用

ThreadLocal中为什么使用弱引用 补个概念&#xff1a; ThreadLocalMap中的key就是Entry&#xff0c;Entry是一个弱引用&#xff0c;关联了当前ThreadLocal对象。需要存储的数据为值。调用set方法要传入两个参数ThreadLocal对象和要存入ThreadLocal对象的数据。 如下图&#xf…

详细分析Java中的@AllArgsConstructor注解

目录 前言1. 基本知识2. 实战 前言 事情起因是Spring的循环依赖 详情可见&#xff1a;出现The dependencies of some of the beans in the application context form a cycle 解决方法&#xff08;全&#xff09; 1. 基本知识 AllArgsConstructor 是 Lombok 提供的一个注解…

《第一行代码》第二版学习笔记(9)——服务

文章目录 一、线程二、解决异步消息处理机制1、消息组成2、AsyncTask 三、Service1、启动和停止服务2、活动和服务通信3、服务的生命周期4、创建前台服务5、使用IntentService 四、服务的最佳实践 一、线程 android不允许在子线程中更新IU操作 二、解决异步消息处理机制 1、…

【linux软件基础知识】- struct gendisk

在Linux内核中&#xff0c;struct gendisk代表通用块设备。 它是用于管理和表示块设备的基本数据结构&#xff0c;例如硬盘驱动器、固态驱动器和其他存储设备。 struct gendisk 包含各种字段和指针&#xff0c;提供与块设备相关的信息和操作。 struct gendisk 结构的一些重要字…

LeetCode题练习与总结:扰乱字符串--87

一、题目描述 使用下面描述的算法可以扰乱字符串 s 得到字符串 t &#xff1a; 1. 如果字符串的长度为 1 &#xff0c;算法停止 2. 如果字符串的长度 > 1 &#xff0c;执行下述步骤&#xff1a; 在一个随机下标处将字符串分割成两个非空的子字符串。即&#xff0c;如果已…

41.乐理基础-拍号-小节、小节线、终止线

小节线&#xff1a;下图红框中的竖线就是小节线 小节、终止线&#xff1a;最后的终止线就是文字意思表示乐谱结束了&#xff0c;后面没有了 下图中 0.5表示0.5拍&#xff08;八分音符&#xff09;、1表示1拍&#xff08;四分音符&#xff09;、0.25表示0.25拍&#xff08;十六分…

二、Redis五种常用数据类型-String

1、用途 简单的K-V缓存计数器分布式锁session共享分布式ID生成(自增) 2、底层实现结构 Redis底层是c语言实现的&#xff0c;但是并没有使用c的string来表示字符串&#xff0c;而是使用自己的简单动态字符串的抽象类型(simple dynamic string,SDS)。 SDS结构&#xff1a; st…

为什么centos官方版不支持arm架构?

为什么centos官方版不支持arm架构&#xff1f; 1、资源限制&#xff1a;CentOS是由社区维护的开源操作系统&#xff0c;其开发和维护需要大量的人力和物力资源。由于ARM架构的设备相对较少&#xff0c;社区资源有限&#xff0c;因此官方版CentOS选择集中精力在x86架构上进行开发…

编程基础学什么课程内容

编程基础学习的课程内容有&#xff1a;程序设计基础、算法与数据结构、计算机科学原理、面向对象编程、网页开发基础等课程内容&#xff0c;以下是上大学网 (www.sdaxue.com)整理的具体课程或技能领域内容&#xff0c;供大家参考&#xff01; 程序设计基础&#xff08;或计算机…

每日OJ题_DFS解决FloodFill⑦_力扣LCR 130. 衣橱整理(原剑指Offer13机器人的运动范围)

目录 力扣LCR 130. 衣橱整理&#xff08;原剑指Offer13机器人的运动范围&#xff09; 解析代码 力扣LCR 130. 衣橱整理&#xff08;原剑指Offer13机器人的运动范围&#xff09; LCR 130. 衣橱整理 难度 中等 家居整理师将待整理衣橱划分为 m x n 的二维矩阵 grid&#xff…

【精品毕设推荐】基于Javaee的影视创作论坛的设计与实现

点击下载原文及代码 摘 要 随着时代的发展&#xff0c;互联网的出现&#xff0c;给传统影视行业带来的最大便利就是&#xff0c;方便了影视从业人员以及爱好者的交流和互动&#xff0c;而为用户提供一个书写影评&#xff0c;阅读影评以及回复影评的平台&#xff0c;以影评为…

Spring MVC、Spring Boot和Spring Cloud 三者区别和联系

引言 近期在做系统重构的项目工作&#xff0c;在跟开发沟通对接过程中&#xff0c;经常听到他们讲开发框架&#xff1a;Spring MVC、Spring Boot、Spring Cloud&#xff0c;故对这三者进行一些学习了解&#xff0c;下面我针对由来、作用与关联等方面&#xff0c;来总结一下我学…

《第一行代码》第二版学习笔记(8)——网络技术

文章目录 一、Http1、HttpURLConnection2、OKHttp 二、解析JSON格式数据1、使用JSONObject2、使用GSON解析JSON数据 一、Http 1、HttpURLConnection public void run() {HttpURLConnection connection null;BufferedReader reader null;try {URL url new URL("http://…

力扣每日一题114:二叉树展开为链表

题目 中等 提示 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同…

js方法返回类型

在JavaScript中&#xff0c;方法可以是以下几种形式&#xff1a; 1. **函数声明**&#xff1a;传统的函数声明方式。 javascript function greet() { console.log(Hello, World!); } 2. **函数表达式**&#xff1a;使用变量赋值的方式定义函数。 javascript const greet…

2024年CMS市场的份额趋势和使用统计

目前市面上有超过一半的网站都是使用CMS来搭建的&#xff0c;据不完全统计&#xff0c;现在大概有900多种CDM可供选择&#xff0c;以下是最常见的CMS的市场份额和使用率信息&#xff1a; 除了WordPress以外&#xff0c;Shopify和Wix也是比较流行的内容管理系统&#xff0c;尤其…

239 基于matlab的EKF(扩展卡尔曼滤波)_UKF(无迹卡尔曼滤波)_PF(粒子滤波)三种算法的估计结果比较

基于matlab的EKF(扩展卡尔曼滤波)_UKF(无迹卡尔曼滤波)_PF&#xff08;粒子滤波&#xff09;三种算法的估计结果比较&#xff0c;输出估计误差&#xff0c;并单独对粒子滤波进行估计及其置信区间可视化。程序已调通&#xff0c;可直接运行。 239 EKF(扩展卡尔曼滤波) - 小红书 …

php 修改 文件权限 函数chmod()

目录 前言 前言 在PHP中&#xff0c;你可以使用chmod()函数修改文件的权限。该函数接受两个参数&#xff1a;文件路径和新的权限模式。以下是一个示例&#xff1a; php <?php // 文件路径 $filename example.txt;// 新的权限模式&#xff08;例如&#xff1a;0644&#…

一、Redis五种常用数据类型

Redis优势&#xff1a; 1、性能高—基于内存实现数据的存储 2、丰富的数据类型 5种常用&#xff0c;3种高级 3、原子—redis的所有单个操作都是原子性&#xff0c;即要么成功&#xff0c;要么失败。其多个操作也支持采用事务的方式实现原子性。 Redis特点&#xff1a; 1、支持…