43.C++11-lambda表达式的使用
目录
一. 什么是lambda表达式
lambda表达式的本质就是一个函数
1.1 lambda表达式的格式⭐
书写格式为:
[ capture-list ] ( parameters ) mutable -> return-type { statement}
说明:
[ ] 内部的capture-list是捕捉列表:表示这个lambda需要捕捉的变量,捕捉的变量可以在lambda内部使用,捕捉方式分为 值捕捉 和 引用捕捉
() 内部的 paramenters 是参数列表,表示这个lambda的参数。简单来说就是函数的参数
mutable表示能够修改捕捉列表的值,为空表示不能修改。(这个只对值捕捉有影响,如果引用捕捉,无论有无mutable都能够修改)
-> return-type:指定这个lambda表达式的返回类型,即这个函数的返回类型
{}以及内部的statement,表示lambda表达式具体的代码,即这个函数的代码
1.2 捕捉列表
捕捉列表是lambda表达式相对于普通函数所独有的特性
lambda表达式可以捕捉外部变量进行访问和修改
捕捉方式如下: var表示要捕捉的变量
[var] 表示按值捕捉这个变量
[&var] 表示按引用捕捉这个变量
[=] 表示按值捕捉上文所有变量
[&] 表示按引用捕捉上文所有变量
[this] 类中可以捕获this
注意:
1 捕捉方式有传值捕捉,传引用捕捉。且传值捕捉的变量是无法改变的,只有加上了mutable才可以改变
2 父作用域指的是包含lambda表达式的语句块
3 捕捉列表可以由多个捕捉项构成,用逗号隔开。但是不允许重复捕捉,否则会编译错误
4 在块作用域意外的lambda表达式的捕捉列表必须为空
5 lambda表达式仅能捕捉父作用域中的变量,捕捉其他变量会编译出错
二. lambda表达式使用举例
2.1 普通函数
这里定义一个 add函数用于测试
#include <iostream>
int main()
{
// 定义一个两数相加的lambda表达式
auto add = [](int a, int b) -> int
{ return a + b; };
int num1 = 1;
int num2 = 2;
std::cout << add(1, 2) << std::endl;
return 0;
}

2.2 作为可调用对象
STL中默认的sort是按升序排序的,可以通过自带的比较器greater,或者自定义比较函数,结构体对象来进行降序。
更方便的方式是使用lambda表达式
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void test()
{
vector<int> arr;
for (int i = 0; i < 10; i++)
{
arr.emplace_back(rand() % 10000);
}
cout << "排序前:";
for (auto &e : arr)
cout << e << " ";
cout << endl;
//使用lambda表达式作为函数对象
sort(arr.begin(), arr.end(), [](const int &a, const int &b) -> int
{ return a > b; });
cout << "排序后:";
for (auto &e : arr)
cout << e << " ";
cout << endl;
}
int main()
{
srand(time(0) ^ rand());
test();
return 0;
}
运行结果如下:

三. lambda表达式的原理
void test1()
{
int a = 1, b = 2;
auto add = [](const int& a, const int& b)->int {return a + b; };
add(1, 2);
/*
00007FF6198BE4DE mov dword ptr[rbp + 144h], 2
00007FF6198BE4E8 mov dword ptr[rbp + 164h], 1
00007FF6198BE4F2 lea r8, [rbp + 144h]
00007FF6198BE4F9 lea rdx, [rbp + 164h]
00007FF6198BE500 lea rcx, [add]
00007FF6198BE504 call `test1'::`2': : <lambda_1>::operator() (07FF6198BC930h)
*/
}
int main()
{
test1();
return 0;
}
通过汇编代码可以看到,lambda表达式本质是一个对象,底层是通过仿函数实现的,通过重载operator()来实现函数
四. 关于lambda表达式的拷贝问题
思考一下, lambda表达式能否拷贝?
lambda表达式是可以拷贝的!不过能否拷贝需要取决于这个lambda表达式的捕捉列表中的捕捉对象能否拷贝。
如果捕捉对象可以拷贝,这个表达式就能够拷贝。如果捕捉的对象的拷贝是被私有了或者禁用了,这个lambda表达式就无法拷贝
更多推荐



所有评论(0)