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

C++中的Lambda表达式

定义:

在C++中,lambda表达式(也叫匿名函数)是一种可以在代码中定义匿名函数对象的便捷方式。

lambda表达式的基本形式是:

 capture list -> return_type { function body } 。

1)[capture list] 是捕获列表,用于指定lambda表达式所在作用域中的变量如何被捕获(可以是值传递或者引用传递),例如 [&] 表示以引用方式捕获所有外部变量, [=] 表示以值的方式捕获所有外部变量。

2)(parameters) 是参数列表,和普通函数的参数列表类似,用于传递参数给lambda函数。如果没有参数,可以写为空括号 () 。

3)-> return_type 是返回值类型部分,用于指定lambda表达式返回值的类型。如果可以自动推断返回类型,这部分可以省略。

4){ function body } 是函数体,包含了lambda表达式要执行的语句。

例如,有一个 vector 存放整数,我们可以使用lambda表达式来进行排序:

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {5, 2, 8, 1, 9};
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a < b;
});
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}

在这个例子中, [](int a, int b) { return a < b; } 就是一个lambda表达式,作为 std::sort 函数的比较函数,用来指定排序规则。

作用:

1.作为回调函数

许多C++标准库算法需要回调函数来指定操作。比如 std::for_each ,它会对序列中的每个元素执行一个操作,这个操作就可以用lambda表达式来定义。

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
std::for_each(v.begin(), v.end(), [](int i) {
std::cout << i * 2 << " ";
});
return 0;
}

在这个例子中, lambda 表达式 [](int i) { std::cout

2.用于排序和比较操作

在使用 std::sort 等函数时,可以用lambda表达式定义比较规则。

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {4, 2, 7, 1, 9};
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b;
});
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}

这里的lambda表达式 [](int a, int b) { return a > b; } 定义了从大到小的排序规则。

3)事件处理

在一些简单的事件驱动编程场景中,lambda表达式可以作为事件处理器。虽然C++不是主要用于事件驱动编程的语言,但在简单的图形界面库或者简单的异步编程场景下可以使用。

#include <iostream>
#include <functional>
class Button {
public:
std::function<void()> onClick;
};
int main() {
Button button;
button.onClick =  {
std::cout << "Button Clicked!" << " ";
};
button.onClick();
return 0;
}

这个例子简单模拟了一个按钮点击事件, lambda 表达式  { std::cout

捕获变量的类型:

1.局部自动变量(栈变量)

这是最常见的情况。例如在一个函数内部定义的普通变量。

#include <iostream>
int main() {
int num = 10;
// 捕获局部自动变量num
auto lambda = num {
std::cout << num << std::endl;
};
lambda();
return 0;
}

在这个例子中,lambda表达式捕获了函数 main 中的局部变量 num 。

2.静态局部变量

可以捕获在函数内定义的静态变量。

#include <iostream>
int main() {
static int static_num = 20;
auto lambda = static_num {
std::cout << static_num << std::endl;
};
lambda();
return 0;
}

这里lambda表达式捕获了静态局部变量 static_num 。

3.类成员变量(在类的成员函数中)

当lambda表达式在类的成员函数中定义时,可以捕获类的成员变量。不过要注意捕获方式和成员访问权限等问题。

#include <iostream>
class MyClass {
public:
int member_var = 30;
void func() {
// 捕获类成员变量member_var
auto lambda = this {
std::cout << this->member_var << std::endl;
};
lambda();
}
};
int main() {
MyClass obj;
obj.func();
return 0;
}

在这个类的成员函数 func 中,lambda表达式通过 [this] 捕获了类 MyClass 的成员变量 member_var 。

捕获方式:

1.按值捕获([=])

会捕获lambda表达式所在作用域的所有变量,并且以副本的形式使用这些变量。

#include <iostream>
int main() {
int num = 10;
auto lambda = = {
std::cout << num << std::endl;
};
lambda();
num = 20;
lambda();
return 0;
}

在这个例子中,lambda表达式按值捕获了 num 变量。即使在调用lambda表达式后修改 num 的值,lambda表达式内部使用的 num 值依旧是捕获时的值(10)。

2.按引用捕获([&])

捕获lambda表达式所在作用域的所有变量的引用,对捕获变量的修改会影响外部变量。

#include <iostream>
int main() {
int num = 10;
auto lambda = & {
std::cout << num << std::endl;
num = 20;
};
lambda();
std::cout << num << std::endl;
return 0;
}

这里lambda表达式按引用捕获 num ,在lambda表达式内部修改 num 的值,外部的 num 变量也会随之改变。

3.混合捕获([=, &var]或者[&, =var])

可以指定部分变量按值捕获,部分变量按引用捕获。例如 [=, &num] 表示除了 num 按引用捕获外,其他变量按值捕获。

#include <iostream>
int main() {
int num1 = 10;
int num2 = 20;
auto lambda = =, &num1 {
std::cout << num1 << " " << num2 << std::endl;
num1 = 30;
};
lambda();
std::cout << num1 << std::endl;
return 0;
}

在这个lambda表达式中, num1 按引用捕获, num2 按值捕获。修改 num1 的值会影响外部变量 num1 的值。

4.捕获特定变量([var])

只捕获指定的变量,并且以副本形式捕获。

#include <iostream>
int main() {
int a = 5, b = 10;
auto lambda = a {
std::cout << a << std::endl;
};
lambda();
return 0;
}

此lambda表达式仅捕获 a 变量, b 变量未被捕获,在lambda表达式内部无法访问 b 。


http://www.kler.cn/a/414639.html

相关文章:

  • sqlmap使用过程中的每个步骤及其相关命令
  • Laravel8.5+微信小程序实现京东商城秒杀方案
  • 03-控制结构
  • JDBC 设置 PostgreSQL 查询中 any(?) 的参数
  • javax.xml.ws.soap.SOAPFaultException: ZONE_OFFSET
  • Python中的23种设计模式:详细分类与总结
  • 【Code First】.NET开源 ORM 框架 SqlSugar 系列
  • 林业推荐系统开发:Spring Boot高级技巧
  • Linux定时器机制实现循环确定时间
  • 使用 OpenCV 进行视频中的行人检测
  • 【Web前端】如何构建简单HTML表单?
  • Vue 路由配置与环境差异问题解析:开发与生产环境中的行为差异
  • 大数据新视界 -- Hive 函数应用:复杂数据转换的实战案例(下)(12/ 30)
  • 解决 Vim 上下左右变成 ABCD 的问题
  • 技术总结(四十)
  • springboot331“有光”摄影分享网站系统pf(论文+源码)_kaic
  • CTF-RE 从0到 N: 高版本 APK 调试 + APK逻辑修改再打包 + os层调试[2024 强网杯青少年专项赛 Flip_over] writeup
  • 50-基于单片机和传感器的冷链运输设计
  • 实战丨证券 HTAP 混合业务场景的难点问题应对
  • python代码示例(读取excel文件,自动播放音频)
  • Flink (Windows Function 窗口函数)
  • [Maven]3.5.3配置
  • HTTP超文本协议
  • Python轴承故障诊断 (21)基于VMD-CNN-BiTCN的创新诊断模型
  • C++练级计划-> 《IO流》iostream fstream sstream详解
  • 操作系统 | 学习笔记 | 王道 | 2.1 进程与线程