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

C++11 lambda 表达

在 C++11 中,lambda 表达式是一个非常重要且强大的特性,允许在代码中定义匿名函数并立即使用它。Lambda 表达式的解析可以从语法结构、捕获列表、参数和返回类型等方面进行详细分析。

Lambda 表达式的基本语法结构

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

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

  • 捕获列表 -> 返回类型 { 函数体 }
  • 捕获列表:指定外部变量的捕获方式(按值或按引用),捕获的变量可以在 lambda 内部使用。
  • 参数列表:可以像普通函数一样定义 lambda 的参数。
  • 返回类型:指定 lambda 函数的返回类型,可以省略,编译器会自动推断。
  • 函数体:定义 lambda 的执行代码。

1. 捕获列表 (Capture List)

捕获列表是 lambda 表达式中的一个重要部分,用来捕获外部作用域中的变量。这些变量可以是按值捕获或按引用捕获,决定了 lambda 内部是否能够修改外部变量。

1.1 按值捕获

按值捕获会将外部变量的副本传递给 lambda 表达式。lambda 内部无法修改原始变量。

int x = 10;
auto lambda = [x]() { std::cout << "x inside lambda: " << x << std::endl; 
};
lambda();  // 输出 "x inside lambda: 10"

1.2 按引用捕获

按引用捕获会将外部变量的引用传递给 lambda 表达式,使得 lambda 内部能够修改外部变量。

int x = 10;
auto lambda = [&x]() { x += 5; std::cout << "x inside lambda: " << x << std::endl; 
};
lambda();  // 输出 "x inside lambda: 15"
std::cout << "x outside lambda: " << x << std::endl;  // 输出 "x outside lambda: 15"

1.3 捕获所有变量

你可以使用 [] 捕获所有外部变量。

  • [=] 按值捕获所有外部变量。
  • [&] 按引用捕获所有外部变量。
int x = 10, y = 20;
auto lambda = [=]() {std::cout << "x: " << x << ", y: " << y << std::endl;  // 按值捕获
};
lambda();  // 输出 "x: 10, y: 20"auto lambda2 = [&]() {x += 5;y += 10;std::cout << "x: " << x << ", y: " << y << std::endl;  // 按引用捕获
};
lambda2();  // 输出 "x: 15, y: 30"
std::cout << "x: " << x << ", y: " << y << std::endl;  // 输出 "x: 15, y: 30"

2. 参数列表 (Parameters List)

Lambda 表达式支持定义输入参数,类似于普通的函数。

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

3. 返回类型 (Return Type)

Lambda 的返回类型可以省略,编译器会根据 return 语句自动推断。但如果编译器无法推断,或希望指定返回类型,则需要显式声明返回类型。

auto multiply = [](int a, int b) -> int { return a * b; };
std::cout << multiply(3, 4);  // 输出 12

4. 函数体 (Function Body)

函数体部分包含 lambda 表达式的执行逻辑。你可以像普通函数一样在 lambda 中编写代码。

auto greet = []() { std::cout << "Hello, world!" << std::endl; };
greet();  // 输出 "Hello, world!"

5. 推导和类型

C++11 中的 lambda 表达式可以自动推导类型,但也允许你显式指定返回类型和参数类型。编译器通常会根据返回值推断返回类型,但如果你明确知道返回类型或有需要的情况下,可以手动指定。

5.1 推导返回类型

auto func = [](int a, int b) { return a + b; };  // 返回类型推导为 int

5.2 显式返回类型

auto func = [](int a, int b) -> double { return a / b; };  // 显式指定返回类型为 double

6. Lambda 表达式的类型

Lambda 表达式的类型是一个匿名的类类型。这个类型是由编译器自动生成的,且每个 lambda 表达式都有独特的类型。

auto lambda = [](int a, int b) { return a + b; };

lambda 是一个类型为 operator() 的对象,它的类型由编译器推断为一个匿名类。
如果你试图手动推导 lambda 的类型,可以使用 std::function 来保存它。

std::function<int(int, int)> add = [](int a, int b) { return a + b; };

7. 使用 Lambda 表达式与 STL 算法

Lambda 表达式在 C++ 中常与标准库算法(如 std::sort、std::find_if 等)配合使用,极大简化了代码。

7.1 使用 lambda 进行排序

#include <algorithm>
#include <vector>
#include <iostream>int main() {std::vector<int> vec = {5, 1, 3, 2, 4};std::sort(vec.begin(), vec.end(), [](int a, int b) { return a < b; });for (int n : vec) {std::cout << n << " ";  // 输出 1 2 3 4 5}return 0;
}

7.2 使用 lambda 查找元素

#include <algorithm>
#include <vector>
#include <iostream>int main() {std::vector<int> vec = {5, 1, 3, 2, 4};auto it = std::find_if(vec.begin(), vec.end(), [](int x) { return x == 3; });if (it != vec.end()) {std::cout << "Found: " << *it << std::endl;  // 输出 "Found: 3"}return 0;
}

总结

C++11 引入的 lambda 表达式使得函数式编程成为可能,并为许多编程场景(如 STL 算法等)提供了简洁的解决方案。Lambda 表达式的关键特点在于:

  • 捕获外部变量:允许按值或按引用捕获外部作用域中的变量。
  • 简洁性:可以定义匿名函数并在代码中直接使用,避免了传统函数定义的冗长。
  • 自动推导:能够自动推导返回类型和参数类型,减少了代码量。
  • 匿名类型:每个 lambda 表达式都有自己的类型,可以通过 std::function 等方式进行存储和使用。
http://www.lqws.cn/news/444817.html

相关文章:

  • c++读写锁
  • CppCon 2017 学习:folly::Function A Non-copyable Alternative to std::function
  • AWK在网络安全中的高效应用:从日志分析到威胁狩猎
  • 基于Python的机动车辆推荐及预测分析系统
  • GRBL_UNO R3编译下载
  • 2025虚幻引擎文件与文件夹命名规律
  • 质检滞后?物料浪费?MES系统破解传统制造七大死结
  • 火山引擎TTS使用体验
  • VAE:变分自编码器
  • CHATERM AI:开启云资源氛围管理新篇章!
  • C++位图
  • 数据结构 6(算法)
  • Python 开发环境全栈隔离架构:从 Anaconda 到 PyCharm 的四级防护体系
  • GNSS介绍
  • 李宏毅《生成式人工智能导论》| 第1讲:什么是生成式人工智能
  • 可口可乐的营销转型如何促成Smartwater的新广告活动
  • 攻防演练:1.木马后门文件演练
  • 选择标签词汇功能(单选多选),在文本框展示
  • JS红宝书笔记 8.2 创建对象
  • 使用Dagster资产工厂模式高效管理重复ETL任务
  • 257. 二叉树的所有路径(js)
  • JavaEE->多线程2
  • 使用Haporxy搭建Web群集
  • 网页后端开发(基础4--数据库MySQL)
  • 第一章 空间解析几何与向量代数 ~ 向量的数量积与向量积
  • Linux head 命令
  • 穿不了 NAT 怎么办?用 TURN Server 把墙搬走!
  • 《Go语言圣经》map
  • C#的泛型和匿名类型
  • Nacos:微服务架构的神经中枢与配置大脑