本篇将会介绍Lambda 表达式中的捕获列表。
捕获列表
所谓捕获列表,其实可以理解为参数的一种类型,lambda 表达式内部函数体在默认情况下是不能够使用函数体外部的变量的,这时候捕获列表可以起到传递外部数据的作用。 根据传递的行为,捕获列表也分为以下几种:
C++新特性12_ Lambda 表达式/匿名函数捕获列表[]及应用
1. 值捕获
与参数传值类似,值捕获的前提是变量可以拷贝,不同之处则在于,被捕获的变量在 lambda 表达式被创建时拷贝,而非调用时才拷贝:
#include <iostream>
using namespace std;
int main() {
int t = 10;
//按值捕获,捕获的是声明匿名函数时,捕获列表参数的值
auto f=[t]() mutable{
cout << t << endl;
return t;
};
t = 11;
f();
}
2. 引用捕获
与引用传参类似,引用捕获保存的是引用,值会发生变化。
#include <iostream>
using namespace std;
int main() {
//按引用捕获
int t = 10;
//此处只是一个声明,还未调用
auto f2 = [&t]() mutable {
cout << t << endl;
t = 13;
return t;
};
t = 11;
f2();
cout << t << endl;
}
运行结果:
3. 隐式捕获
手动书写捕获列表有时候是非常复杂的,这种机械性的工作可以交给编译器来处理,这时候可以在捕获列表中写一个 & 或 = 向编译器声明采用 引用捕获或者值捕获.
总结一下,捕获提供了 Lambda 表达式对外部值进行使用的功能,捕获列表的最常用的四种形式可以是:
(1)[] 空捕获列表;
(2)[name1, name2, …] 捕获一系列变量;
(3)[&] 引用捕获, 让编译器自行推导捕获列表;
(4)[=] 值捕获, 让编译器执行推导应用列表;
//捕获列表
int a = 1;
int b = 2;
//按值捕获所有变量
[=]() {
cout << a << "+" << b << endl;
}();
//按引用捕获所有变量
[&]() {
cout << a++ << "+" << b++ << endl;
}();
//按值和引用捕获所有变量
[a,&b]() {
cout << a<< "+" << b<<endl;
}();
4. 容器for_each遍历中嵌入Lambda 表达式
利用stl中迭代写法for_each进行动态数组内元素奇偶数的判断。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//应用举例
int main()
{
//常规方法
//判断哪些是奇数,哪些是偶数
vector<int>v = {1,2,3,4,5};
for (int i=0;i<v.size();i++)
{
if (v[i] % 2 == 0)
{
cout << v[i] << "是偶数" << endl;
}
else {
cout << v[i] << "是奇数" << endl;
}
}
//高阶写法,for_each,stl中提供的迭代的写法
//起始,结尾,每遍历一次执行的匿名函数
//每一次调用就会将值传给n
for_each(v.begin(), v.end(), [](int n) {
if (n % 2 == 0)
{
cout << n << "是偶数" << endl;
}
else {
cout << n << "是奇数" << endl;
}
});
return 0;
//未能实现,时间问题后期再研究:迭代器中auto不能用于参数所以失败(20230609)
//利用迭代器iterator进行遍历,并应用匿名函数
//for (auto it : v)
for (auto it = v.begin(); it != v.end(); it++)
{
[&](int n) {
if (n % 2 == 0)
{
cout << n << "是偶数" << endl;
}
else {
cout << n << "是奇数" << endl;
}
};
}
上面的明显存在问题,为什么不直接使用以下迭代方式遍历,用Lambda表达式很多余
for (auto it = v.begin(); it != v.end(); it++)
{
if (*it % 2 == 0)
{
cout << *it << "是偶数" << endl;
}
else {
cout << *it << "是奇数" << endl;
}
}
}
迭代器:C++新特性03_迭代器iterator及类型推导auto
5.学习视频地址: Lambda 表达式/匿名函数捕获列表及应用
6.学习笔记:Lambda 表达式/匿名函数捕获列表及应用笔记