当前位置: 首页 > news >正文

【C++基础】Lambda 函数 基础知识讲解学习及难点解析

一、引入

在 C++ 中,我们通常使用函数来完成特定的功能。但有时候,我们需要在一个函数内部定义一个小型的功能块,这时如果单独写一个函数会显得繁琐。C++11 引入了 Lambda 函数,它是一种匿名函数,可以在需要的地方直接定义和使用,非常适合用于简化代码。

二、Lambda函数的基本用法

1.语法模板(看不懂没关系,看完实例就理解了)

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

逐部分讲解

1.捕获列表 []:

用于捕获外部变量,决定 Lambda 函数如何访问外部作用域的变量。

常见形式:

[]:不捕获任何变量。

[=]:以值的方式捕获所有外部变量。

[&]:以引用的方式捕获所有外部变量。

[x, &y]:以值捕获 x,以引用捕获 y。

2.参数列表 ():

和普通函数的参数列表一样,用于传递参数。

3.返回类型 -> 返回类型:

可以省略,编译器会自动推导返回类型。

如果函数体中有多个返回语句,且类型不一致,则需要显式指定返回类型。

4.函数体 {}:

实现具体的功能逻辑。

示例

auto add = [](int a, int b) -> int {
    return a + b;
};
std::cout << add(2, 3); // 输出: 5

三、 Lambda 函数的捕获列表详解

示例 1:不捕获任何变量

int x = 10;
auto func = []() {
    // x 不可访问,编译错误
    // std::cout << x;
};

示例 2:以值的方式捕获变量

int x = 10;
auto func = [x]() {
    std::cout << x; // 输出: 10
};
x = 20;
func(); // 输出仍然是 10,因为捕获的是值

此时函数捕获的是x的数值:10,而不是x这个变量,因此外界对x更改不会影响函数中10这个数

示例 3:以引用的方式捕获变量

int x = 10;
auto func = [&x]() {
    std::cout << x; // 输出: 10
};
x = 20;
func(); // 输出: 20,因为捕获的是引用

此时函数捕获的是x这个变量,区别于上面那种

示例 4:混合捕获

int x = 10, y = 20;
auto func = [x, &y]() {
    std::cout << x << " " << y; // 输出: 10 20
    y = 30; // 修改 y 的值
};
func();
std::cout << y; // 输出: 30

四、Lambda 函数的实际应用

示例 :STL 算法中的 Lambda 函数

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> nums = {3, 1, 4, 1, 5, 9};
    std::sort(nums.begin(), nums.end(), [](int a, int b) {
        return a > b; // 降序排序
    });
    for (int num : nums) {
        std::cout << num << " "; // 输出: 9 5 4 3 1 1
    }
    return 0;
}

五、总结与注意事项

总结

  1. Lambda 函数是一种匿名函数,适合用于简化代码和实现小型功能。

  2. 捕获列表决定了 Lambda 函数如何访问外部变量。

  3. Lambda 函数常用于 STL 算法和回调函数中。

注意事项

  1. 捕获列表的使用需要谨慎,避免不必要的值拷贝或引用捕获。

  2. 如果 Lambda 函数的逻辑较复杂,建议单独写一个普通函数。

六、易混辨析与深入理解

1.[ ]< >的大乱斗

(1)两者区别

特性[](捕获列表)<>(模板参数列表)
用途用于 Lambda 函数,定义如何捕获外部变量用于模板,定义类型参数
位置出现在 Lambda 函数的开头出现在模板类或模板函数的定义或调用处
内容捕获方式(值、引用等)类型参数(如 int等)

它们的作用域和语法规则是独立的,没有任何关联。

(2)如何选取

int x = 10;
auto func = [x](int y) -> int {
    return x + y; // 捕获 x,参数 y
};
std::cout << func(5); // 输出: 15

例如上面的程序,为什么不写成下面的:

int x = 10;
auto func = [](int x,int y) -> int {
    return x + y; 
};
std::cout << func(x,5); // 输出: 15

分析解答:

特性直接传递参数使用捕获列表
依赖外部变量不依赖,x 通过参数传递依赖,x 通过捕获列表捕获
参数传递每次调用都需要显式传递 xx 在 Lambda 函数内部直接可用
性能可能产生额外的拷贝开销引用捕获可以避免拷贝开销
代码可读性更直观,逻辑清晰可能降低可读性,尤其是捕获列表复杂时
适用场景适合简单的、独立的功能适合需要封装外部状态的场景

 (3)为什么选择捕获列表?

场景 1:封装外部状态
int x = 10;
auto func = [x]() {
    std::cout << "Captured x: " << x;
};
x = 20; // 修改外部 x
func(); // 输出: Captured x: 10
场景 2:避免重复传递参数
int x = 10;
auto func = [x](int y) {
    return x + y; // 不需要每次调用都传递 x
};
std::cout << func(5); // 输出: 15
std::cout << func(10); // 输出: 20
场景 3:引用捕获避免拷贝
std::vector<int> data = {1, 2, 3};
auto func = [&data]() {
    data.push_back(4); // 修改外部 data
};
func();
std::cout << data.size(); // 输出: 4

2.[&] 和 [&x]的区别

[&]:以引用的方式捕获所有外部变量

作用:捕获所有外部变量,并以引用的方式访问它们。

  • 特点

    • 简洁,不需要显式列出所有变量。

    • 适合需要捕获多个变量的场景。

    • 可读性较差,因为不清楚具体捕获了哪些变量。

[&x]:以引用的方式捕获特定变量

作用:只捕获指定的变量 x,并以引用的方式访问它。

  • 特点

    • 明确,清楚地知道捕获了哪个变量。

    • 适合只需要捕获少量变量的场景。

    • 可读性较好,但可能会显得冗长。

相关文章:

  • OpenCV旋转估计(4)生成一个字符串表示的匹配图函数 matchesGraphAsString()
  • 区块链学习总结
  • DDT数据驱动
  • 说一下yolo的一些概念 和 自己对 置信度阈值 和图像处理模板匹配的理解
  • java设计模式之建造者模式《装修启示录》​
  • 基于DrissionPage的DY无水印视频采集
  • C++与OO思想的联系
  • React 18 如何定义变量,及赋值 与渲染
  • python网络爬虫开发实战之网页数据的解析提取
  • docker常见的命令详细介绍
  • java小白日记38(集合-List)
  • 来源于胡椒的亚甲二氧桥CYP450-文献精读119
  • Android Window浮窗UI组件使用JetPack
  • 剑指 Offer II 111. 计算除法
  • 如何在 Linux 系统中部署 FTP 服务器:从基础配置到安全优化
  • Softmax温度调节与注意力缩放:深度神经网络中的平滑艺术
  • iStoreOS软路由对硬盘格式化分区(转化ext4)
  • Redisson分布式锁(超时释放及锁续期)
  • 已安装MFC,仍然提示“error MSB8041: 此项目需要 MFC 库”
  • 14:00面试,15:00就出来了,问的问题过于变态了。。。
  • 工行回应两售出金条疑似有杂质:情况不属实,疑似杂质应为金条售出后的外部附着物
  • 中铁房地产24.7亿元竞得上海松江新城宅地,溢价率20.42%
  • 英国和美国就关税贸易协议条款达成一致
  • 泉州一家婚介机构广告牌越南新娘七天闪婚领证?市监部门介入
  • 罗氏制药全新生物制药生产基地投资项目在沪启动:预计投资20.4亿元,2031年投产
  • 新消费观察| 零售品牌 “走出去” ,如何开辟“新蓝海”?