[C++11] Lambda表达式完整解析

说明:C++11中的Lambda表达式是一种允许创建匿名函数对象的语法结构。Lambda表达式可以捕获作用域中的变量,并且可以像普通函数一样被调用。它们是C++11标准中引入的一个重要特性,旨在提供一种方便的方式来定义内联的小型函数,特别适用于编写回调函数、线程任务、以及与STL算法结合使用的场景。

Lambda表达式的基本语法如下:

[捕获列表](参数列表) -> 返回类型 {函数体
}

其中概念解读如下:

  • 捕获列表:定义了Lambda表达式可以访问的外部变量。可以捕获值、引用或不捕获(默认情况下,Lambda不能访问外部变量)。
  • 参数列表:与普通函数的参数列表类似,可以有或没有参数,参数列表也可以省略。
  • 返回类型:Lambda表达式的返回类型可以显式指定,也可以由编译器根据函数体自动推导。
  • 函数体:包含Lambda表达式的代码实现。

在使用Lambda表达式前我们先了解下为什么引入Lambda表达式。知其然知其所以然。

1 C++11 为什么引入Lambda表达式?

C++11引入Lambda表达式的目的是为了提供一种方便、灵活且表达性强的方式来定义匿名函数。Lambda表达式的引入主要是基于以下几个原因和目标:

  • 代码封装和复用:Lambda表达式允许在代码中直接定义函数对象,这有助于封装一小段相关的代码,使得代码更加模块化。这种方式可以减少额外的函数定义,避免全局函数的污染,并且使得相关功能更加紧凑和易于复用。
  • 简洁性:在C++11之前,如果需要传递一个函数作为参数或者在循环中使用一个临时的函数对象,程序员通常需要定义一个命名的函数或者使用函数指针。Lambda表达式提供了一种更加简洁的方式来创建这些临时的函数对象,从而简化了代码。
  • 捕获上下文:Lambda表达式可以捕获其创建时周围的变量,这使得Lambda表达式可以访问定义它的函数的局部变量。这种特性非常有用,尤其是在需要使用到这些局部变量的回调函数或者模板函数中。
  • 支持函数式编程范式:Lambda表达式是函数式编程范式的一个重要组成部分。通过引入Lambda表达式,C++开始支持更多的函数式编程技术,如高阶函数、闭包等,这为程序员提供了更多的编程选择和灵活性。
  • 与STL和算法结合:STL(Standard Template Library)是C++的一个重要组成部分,它提供了一系列模板化的容器和算法。Lambda表达式可以非常方便地与STL算法结合使用,作为算法的参数传递,从而实现各种复杂的操作,如过滤、转换、查找等。
  • 增强表达力:Lambda表达式增强了C++的表达力,使得一些原本需要复杂模板元编程或宏定义的功能,现在可以用更加直观和易于理解的方式来实现。
  • 适应多核和并行计算:随着多核和多线程计算的普及,Lambda表达式提供了一种方便的方式来定义并行任务。结合C++11的线程库和其他并行编程库,Lambda表达式可以轻松地在多线程环境中使用。
  • 与现代C++开发相适应:随着C++语言的发展,现代C++开发趋向于更加简洁、模块化和函数式。Lambda表达式的引入是与这一趋势相适应的,它使得C++能够更好地与其他现代编程语言接轨。

综上所述,Lambda表达式的引入是为了提高C++的编程灵活性、代码的可读性和编写效率,同时也使得C++能够更好地适应现代编程的需求和趋势。

2 Lambda表达式使用详解

Lambda表达式是C++11中一个非常强大的特性,它允许你定义一个匿名函数对象,可以在定义它的地方立即使用,或者将其赋给一个变量以便稍后使用。Lambda表达式在STL算法、多线程编程、回调机制等多种场景中都非常有用。以下是一些详细的例子,展示了Lambda表达式在不同情况下的用法:

2.1 简单的Lambda表达式

参考代码如下:

// 定义一个Lambda表达式,接受两个int参数,返回它们的和
auto add = [](int a, int b) { return a + b; };
int result = add(2, 3); // 调用Lambda表达式,result 为 5

2.2 使用Lambda表达式与STL算法

参考代码如下:

#include <vector>
#include <algorithm>std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用Lambda表达式作为std::for_each的第一个参数
std::for_each(numbers.begin(), numbers.end(), [](int num) {std::cout << num << std::endl; // 打印每个数字
});
// 使用Lambda表达式进行排序,根据数字的奇偶性
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {return a % 2 == 0 && b % 2 != 0;
});

2.3 捕获上下文变量

参考代码如下:

// 定义一些局部变量
int x = 10;
int y = 20;
// 定义一个Lambda表达式,捕获x和y
auto lambda = [&x, &y]() { return x + y; };
int result = lambda(); // 调用Lambda表达式,result 为 30

2.4 在多线程编程中使用Lambda表达式

参考代码如下:

#include <iostream>
#include <thread>void print(int n) {std::cout << "Hello from thread " << n << std::endl;
}int main() {std::thread t(print, 1); // 使用Lambda表达式启动线程t.join(); // 等待线程结束return 0;
}

2.5 Lambda表达式作为函数参数

参考代码如下:

// 定义一个接受Lambda表达式作为参数的函数。
void executeLambda(std::function<void()> lambda) {lambda(); // 调用传入的Lambda表达式
}int main() {executeLambda([]() {std::cout << "Lambda is called" << std::endl;});return 0;
}

2.6 使用Lambda表达式进行类型推导

参考代码如下:

// 使用auto推导Lambda表达式的类型。
auto square = [](int x) -> int {return x * x;
};
int squared = square(5); // squared 为 25

2.7 Lambda表达式与模板函数结合

参考代码如下:

template <typename Func>
void runFunc(Func f) {f();
}int main() {runFunc([]() {std::cout << "Hello from a template function!" << std::endl;});return 0;
}

2.8 Lambda表达式捕获所有局部变量

参考代码如下:

// 定义一些局部变量
int a = 5;
int b = 10;
// 定义一个Lambda表达式,捕获所有局部变量
auto lambda = [a, b]() {std::cout << "a = " << a << ", b = " << b << std::endl;
};
lambda(); // 输出:a = 5, b = 10

通过这些例子,我们可以看到Lambda表达式在C++11中的多样性和实用性。它不仅可以简化代码,还可以提高代码的可读性和可维护性。Lambda表达式的引入为C++编程带来了更多的灵活性和便利。

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

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

相关文章

关于 HEAP CORRUPTION DETECTED:after Normal block 错误的原因及解析

目录 一、HEAP CORRUPTION DETECTED:after Normal block 出现的报错情况&#xff1a; 二、问题原因&#xff08;重要&#xff09;&#xff1a; 三、举例 1.错误代码如下&#xff1a; 2.错误原因及分析&#xff08;重要&#xff09;&#xff1a; 3.解决方法 ​编辑 4.正…

JavaScript 窗口

1.打开新窗口&#xff1a;window.open() <button onclick"isOpen()">打开百度</button> <script> function isOpen(){ myBaidu window.open(http://www.baidu.com); } </script> 2.关闭当前窗口&#xff1a;window.close() <button on…

【Linux C | 多线程编程】线程的连接、分离,资源销毁情况

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-04-01 1…

SSM框架学习——MyBatis关联映射

MyBatis关联映射 为什么要关联映射 实际开发中&#xff0c;对数据库操作常常会涉及多张表&#xff0c;所以在OOP中就涉及对象与对象的关联关系。针对多表操作&#xff0c;MyBatis提供关联映射。 关联关系概述 一对一&#xff1a;A类中定义B类的属性b&#xff0c;B类中定义A…

MCU友好过渡MPU,米尔基于STM32MP135开发板裸机开发应用笔记

以前微处理器&#xff08;MPU&#xff09;与微控制器&#xff08;MCU&#xff09;是截然不同的两种设备&#xff0c;MPU支持丰富的软件系统&#xff0c;如Linux和相关的软件堆栈&#xff0c;而MCU通常将专注于裸机和RTOS。近年来&#xff0c;随着MCU的性能越来越高&#xff0c;…

【Spring源码】WebSocket做推送动作的底层实例

一、前瞻 Ok&#xff0c;开始我们今天的对Spring的【模块阅读】。 那就挑Web里的WebSocket模块&#xff0c;先思考下本次阅读的阅读线索&#xff1a; WebSocket在Spring里起到什么作用这个模块采用了什么设计模式我们都知道WebSocket可以主动推送消息给用户&#xff0c;那做推…

Netty空闲检测Keepalive

文章目录 前言一、空闲检测二、Keepalive机制总结 前言 Netty的空闲检测和Keepalive机制都是为了确保客户端和服务器之间的连接仍然有效&#xff0c;防止连接断开。但它们在实现方式和原理上有所不同。 Netty的空闲检测机制是一种自定义的、基于应用层的机制。它主要通过定时…

halcon图像膨胀

1、原理&#xff1a; 使用结构元素在图像上移动&#xff0c;如果结构元素中有任意一个像素和图像上的非零像素重叠&#xff0c;则保留此时结构元素中心所在位置&#xff0c;并将其像素值设置为非零。 2、halcon代码 其中圆形结构元素可设置半径&#xff0c;矩形结构元素设置…

Leetcode509——斐波那契数(C语言)

题目来源&#xff1a;509. 斐波那契数 - 力扣&#xff08;LeetCode&#xff09; 方法一&#xff1a;&#xff08;动态规划&#xff09; 首先找到斐波那契数的边界条件F(0)0 和 F(1)1。 当n>1时&#xff0c;每项的和都等于前两项的和&#xff0c;即&#xff1a;F(n)F(n−1)F(…

设计模式(7):装饰器模式

一.装饰器模式职责&#xff1a; 动态的为一个对象增加新的功能&#xff1b;装饰器是一种用于代替继承的技术&#xff0c;无须通过继承增加子类就能扩展对象的新功能&#xff0c;使用对象的关联关系代替继承关系&#xff0c;更加灵活&#xff0c;同时避免类型体系的快速膨胀。 …

MySQL故障排查与生产环境优化

一、MySQL单实例常见故障 1.逻辑架构图 MySQL逻辑架构图客户端和连接服务核心服务功能存储引擎层数据存储层 2.故障一 故障现象 ERROR 2002 (HY000): Cant connect to local MySQL server through socket/data/mysql/mysql.sock(2) 问题分析 数据库未启动或者数据库端口…

C++ 数学函数、头文件及布尔类型详解

C 数学 C 有许多函数可以让您在数字上执行数学任务。 最大值和最小值 max(x, y) 函数可用于找到 x 和 y 的最大值&#xff1a; 示例 cout << max(5, 10);而 min(x, y) 函数可用于找到 x 和 y 的最小值&#xff1a; 示例 cout << min(5, 10);C <cmath>…

Yolo 自制数据集dect训练改进

上一文请看 Yolo自制detect训练-CSDN博客 简介 如下图&#xff1a; 首先看一下每个图的含义 loss loss分为cls_loss, box_loss, obj_loss三部分。 cls_loss用于监督类别分类&#xff0c;计算锚框与对应的标定分类是否正确。 box_loss用于监督检测框的回归&#xff0c;预测框…

蓝桥杯真题:成绩统计

这题思路简单&#xff0c;但是输出结果的位置容易出错&#xff0c;题目要求四舍五入&#xff0c;所以要用Math.round&#xff08;&#xff09;的方法

Python快速入门系列-7(Python Web开发与框架介绍)

第七章:Python Web开发与框架介绍 7.1 Flask与Django简介7.1.1 Flask框架Flask的特点Flask的安装一个简单的Flask应用示例7.1.2 Django框架Django的特点Django的安装一个简单的Django应用示例7.2 前后端交互与数据传输7.2.1 前后端交互7.2.2 数据传输格式7.2.3 示例:使用Flas…

解决GNU Radio+USRP实现OFDM收发在接收端存在误码问题

文章目录 前言一、OFDM 收发流程1、OFDM 收端流程2、OFDM 收端流程 二、问题所在1、find_trigger_signal 函数解读2、general_work 函数3、问题所在 三、修改源码四、运行结果1、频谱2、传输数据测试 五、调试小技巧六、资源自取 前言 在使用 GNU Radio 时使用官方例程搭建 GN…

git clone没有权限的解决方法

一般情况 git clone时没有权限&#xff0c;一般是因为在代码库平台上没有配置本地电脑的id_rsa.pub 只要配置上&#xff0c;一般就可以正常下载了。 非一般情况 但是也有即使配置了id_rsa.pub后&#xff0c;仍然无法clone代码的情况。如下 原因 这种情况是因为ssh客户端…

前端常用代码整理— js,jquery篇(3)

目录 1.判断是否是json字符串 2.获取当前网址 3.将文本复制到剪贴板 4.获取一个月的天数 5.展平数组 6.要修改getRandomItem函数以返回数组中的随机两个元素&#xff0c;可以尝试以下代码 1.判断是否是json字符串 const isJson str > {try {JSON.parse(str);return …

Java面试题(含答案)4.多线程与并发篇

Java多线程与并发编程是一个广泛而深入的主题&#xff0c;因此涵盖所有可能的面试题和答案是不切实际的。不过&#xff0c;我可以为您提供一些常见的Java多线程与并发编程面试题及其答案&#xff0c;以帮助您准备面试。 面试题1&#xff1a;什么是Java中的线程&#xff1f; 答…

uniapp项目--青年帮新闻项目

文章目录 uniapp项目--青年帮新闻项目1.项目提要2.实际代码 uniapp项目–青年帮新闻项目 1.项目提要 导航滚动实现滚动条消失&#xff0c;使用的效果是渗透。 /deep/ ::-webkit-scrollbar {width: 4px !important;height: 1px !important;overflow: auto !important;backgroun…