系列文章目录
简介
Lambda表达式是一种用于创建匿名函数的语法结构。它可以在需要函数对象的地方使用,而无需显式定义一个命名函数。Lambda表达式在C++中最早出现在C++11标准。
一、特点
- 简洁:Lambda表达式可以快速创建小型函数,无需定义单独的函数或函数对象,使代码更加简洁。
- 适应性强:Lambda表达式可以方便地捕获外部变量,并对其进行操作,增强了代码的灵活性和可重用性。
- 匿名性:Lambda表达式是匿名的,可以在代码中直接使用,无需预先定义或命名。
二、语法结构
[capture list](parameters list) -> return_type { function body }
capture list
:捕获列表,用于指定lambda表达式中使用的外部变量,不可省略。
[]
:表示不捕获任何变量
[var]
:表示捕获变量var;还可以是[var1, var2],表示捕获多个变量
[=]
:值捕获,捕获外部作用域所有变量,在函数体内有个副本
[&]
:引用捕获,捕获值传递外部作用域所有变量,在函数体内当引用使用
[=,&var]
:捕获外部作用域所有变量,按引用捕获变量var
[this]
:捕获当前类中this变量
parameters list
:参数列表,用于指定lambda函数的参数。可省略
return_type
:返回类型,指定lambda函数的返回类型。可省略,编译器会自动推断返回类型。
function body
:lambda函数的具体实现逻辑,不可省略。
三、实例
1.排序
使用Lambda表达式排序
std::sort 是 C++标准库中的一个算法函数,用于对容器中的一系列值进行排序。第三个参数是一个布尔值,用于指定排序的顺序。它决定了元素是按照升序还是降序进行排序。如果第三个参数为true,则元素将按照升序进行排序,即从小到大排列。
如果第三个参数为false,则元素将按照降序进行排序,即从大到小排列。根据C++的排序算法的约定,当lambda函数体(x < y)返回true时,std::sort将把元素x放在元素y的前面。
{
//使用Lambda表达式对容器进行排序
std::vector<int> vi = { 20,10,6,50 };
std::sort(vi.begin(), vi.end(), [](int x, int y) {return x < y; });
// 输出排序后的容器内容
std::cout << "使用Lambda表达式对int类型容器进行排序" << std::endl;
for (auto i : vi)
{
std::cout << i << " ";
}
std::cout << std::endl;
//使用函数来代替lambda表达式对构造体排序
std::vector<Person> personVec1 = { Person{"Tom", 10}, {"Jack", 14}, {"Ben", 9}, {"Mike", 7} };
std::sort(personVec1.begin(), personVec1.end(), IsYounger);
// 输出排序后的容器内容
std::cout << "使用函数对构造体排序" << std::endl;
for (auto person : personVec1)
{
std::cout << person.name.c_str() << " " << person.age << std::endl;
}
//使用重载函数来代替lambda表达式对构造体排序
std::vector<Person> personVec2 = { Person{"Tom", 10}, {"Jack", 14}, {"Ben", 9}, {"Mike", 7} };
std::sort(personVec2.begin(), personVec2.end(), Person());
std::cout << "使用重载函数对构造体排序" << std::endl;
for (auto person : personVec2)
{
std::cout << person.name.c_str() << " " << person.age << std::endl;
}
//使用lambda表达式对构造体排序(常规写法)
std::vector<Person> personVec3 = { Person{"Tom", 10}, {"Jack", 14}, {"Ben", 9}, {"Mike", 7} };
auto IsYounger = [](Person x, Person y) { return x.age < y.age; };
std::sort(personVec3.begin(), personVec3.end(), IsYounger);
std::cout << "使用lambda表达式对构造体排序(常规写法)" << std::endl;
for (auto person : personVec3)
{
std::cout << person.name.c_str() << " " << person.age << std::endl;
}
//使用lambda表达式对构造体排序(匿名函数写法)
std::vector<Person> personVec4 = { Person{"Tom", 10}, {"Jack", 14}, {"Ben", 9}, {"Mike", 7} };
std::sort(personVec4.begin(), personVec4.end(), [](Person x, Person y) {
return x.age < y.age;
});
std::cout << "使用lambda表达式对构造体排序(匿名函数写法)" << std::endl;
for (auto person : personVec4)
{
std::cout << person.name.c_str() << " " << person.age << std::endl;
}
}
2.容器赋值
使用lambda表达式给容器赋值
std::generate 是 C++ 标准库中的一个算法函数,用于生成一系列值并将其存储在容器中。它接受一个范围(由迭代器指定)和一个生成器函数(可以是函数指针、函数对象或 lambda表达式),并使用生成器函数生成值来填充范围内的元素。
{
std::vector<int> tmpVector{ 0,0,0,0,0 };
int i = 10;
int num = 0;
generate(tmpVector.begin(), tmpVector.end(), [i, &num]() {
num = i * i + num;
return num;
});
std::cout << "使用lambda表达给tmpVector赋值" << std::endl;
std::cout << "打印i和num的值,以查看值传递和引用传递的区别" << std::endl;
std::cout << "i=" << i << " num=" << num << std::endl; //输出结果:i=10 num=500
std::cout << "打印tmpVector中的值----------" << std::endl;
for_each(tmpVector.begin(), tmpVector.end(), myPrintf); // 输出结果:100 200 300 400 500
std::cout << std::endl;
}
3.传参
值传递和引用传递形参(和普通函数的值传递和引用传递一样)
{
std::vector<int> tmpVector{ 0,1,2,3,4 };
int tmpNum1 = 10;
int tmpNum2 = 5;
std::cout << "lambda表达默认捕获外部变量,形参以值传递方式" << std::endl;
for_each(tmpVector.begin(), tmpVector.end(), [=](int x) {
x = x * tmpNum1 + tmpNum2;
std::cout << "x=" << x << std::endl; //输出结果:5 15 25 35 45
});
for_each(tmpVector.begin(), tmpVector.end(), myPrintf); //输出结果:0 1 2 3 4
std::cout << std::endl;
std::vector<int> tmpVector1{ 0,1,2,3,4 };
std::cout << "lambda表达默认捕获外部变量,形参以引用传递方式" << std::endl;
for_each(tmpVector1.begin(), tmpVector1.end(), [=](int &x) {
x = x * tmpNum1 + tmpNum2;
std::cout << "x=" << x << std::endl; // 输出结果:5 15 25 35 45
});
for_each(tmpVector1.begin(), tmpVector1.end(), myPrintf); //输出结果:5 15 25 35 45
std::cout << std::endl;
}