目录
1.lambda引入
2.语法
3.捕捉列表详解
[ ] 不捕获任何外部变量
[=] 捕获父作用域的所有变量的值,只读不可以修改
[&]捕获父作用域的所有变量的引用,可修改捕获的变量
[val] 只捕获指定的变量值,不可以修改
[&val] 只捕获外部变量val的引用
[this] 捕获当前类的this指针
[=,&]混合
4.mutable
1.lambda引入
在C++98中如想对数据集合中的数据进行排序,需要使用sort函数,该函数默认升序
#include <functional>
#include <algorithm>
int main()
{int arr[] = { 1,2,6,7,4,3,8 };sort(arr, arr + sizeof(arr) / sizeof(arr[0])); for (auto& e : arr)cout << e;cout<<endl;sort(arr, arr + sizeof(arr) / sizeof(arr[0]),greater<int>());for (auto& e : arr)cout << e;return 0;
}
但如果数据对象是自定义类型就需要用户自己写比较函数
#include <vector>
#include <string>
#include <algorithm>class fruit
{
public:fruit(string name,int price,int num) :_name(name),_price(price),_num(num){}int _price;int _num;string _name;
};struct ComparePriceLess
{bool operator()(const fruit& f1, const fruit& f2){return f1._price < f2._price;}
};struct ComparePriceGreater
{bool operator()(const fruit& f1, const fruit& f2){return f1._price > f2._price;}
};
int main()
{vector<fruit> v = { { "苹果", 2, 5 }, { "香蕉", 3, 4 }, { "橙子", 2,3 }, { "菠萝", 1, 4 } };sort(v.begin(), v.end(), ComparePriceLess());for (auto& e : v)cout<<e._name;return 0;
}
2.语法
但是显然这样的方式每次都要今次那个不同功能的实现,自己手写实在不方便
引入lambda表达式:本质是一个含有operator()的匿名接口(或者类)
lambda的语法:
[capture list] (params list) mutable -> return type { function body }
capture list:捕捉列表,捕获的外部变量列表,可以为空,[ ]开头告诉编译器,现在要用lambda函数
params list:参数列表,与普通函数的形参列表是一样的,如果不需要传递参数,可以连()一起省略
mutable:lambda函数总是一个const函数,但是使用mutable可以取消其常性,使用它的时候,参数列表不能为空,即使参数为空
return type:返回值类型,用追踪返回类型形式声明函数的返回值类型,没有返回值的时候这部分可以省略,返回值类型明确的情况下也可以省略,由编译器对返回值类型推导
function body:函数体,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。
在lambda中参数列表和返回值类型可以省略,但是捕捉列表和函数体是不能省略的,最简单的lambda函数是[ ]{ },该函数不能做任何事情
那么上面的比较函数可以用lambda函数表示成
#include <vector>
#include <string>
#include <algorithm>class fruit
{
public:fruit(string name,int price,int num) :_name(name),_price(price),_num(num){}int _price;int _num;string _name;
};struct ComparePriceLess
{bool operator()(const fruit& f1, const fruit& f2){return f1._price < f2._price;}
};struct ComparePriceGreater
{bool operator()(const fruit& f1, const fruit& f2){return f1._price > f2._price;}
};
int main()
{vector<fruit> v = { { "苹果", 2, 5 }, { "香蕉", 3, 4 }, { "橙子", 2,3 }, { "菠萝", 1, 4 } };sort(v.begin(), v.end(), ComparePriceLess());for (auto& e : v)cout << e._name;cout << endl;sort(v.begin(), v.end(), [](const fruit& f1, const fruit& f2){return f1._price < f2._price;});for (auto& e : v)cout<<e._name;return 0;
}
3.捕捉列表详解
下面所说的父作用域是指包含lambda函数的语句块
在块作用域以外的lambda函数捕捉列表必须为空
在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错
[ ] 不捕获任何外部变量
int main()
{int i = 1;auto func=[](int i) { cout << i << endl; };func(i);return 0;
}
[=] 捕获父作用域的所有变量的值,只读不可以修改
int main()
{int i = 1;auto func=[=]() { cout << i << endl; }; //没有形参 而是直接捕捉ifunc();return 0;
}
[&]捕获父作用域的所有变量的引用,可修改捕获的变量
int main()
{int i = 1;auto func=[&]() { cout << ++i << endl; };func();return 0;
}
[val] 只捕获指定的变量值,不可以修改
int main()
{int i = 1,j = 2;auto func=[j]() { cout << i << endl; };func();return 0;
}
报错是因为只捕获了j但是没有捕获i
[&val] 只捕获外部变量val的引用
[this] 捕获当前类的this指针
class fruit
{
public:fruit(int price) :_price(price) {}void Getprice(){cout << _price << endl;}void lambda(){auto func = [this]() {this->Getprice();};func();}
private:int _price;
};int main()
{fruit f(1);f.lambda();
}
[=,&]混合
一定要用,隔开,不允许重复捕捉比如[=,a] 这样会导致编译错误
int main()
{int i = 1,j = 2;auto func=[=,&j]() { cout << i <<" "<<++j << endl; };func();return 0;
}
综上可以看出lambda相当于一个无名函数,不能直接调用,但是可以用auto推演出类型然后赋给一个函数变量,调用该变量
此外lambda表达式之间不能相互赋值,即使看起来类型是相同的
4.mutable
mutable关键字说明函数体中可以修改值捕捉的变量,但是不影响外部该变量的值,因为值传递是以拷贝方式实现的
int main()
{int i = 1,j = 2;auto func=[=,&j]()mutable { cout << ++i <<" "<<++j << endl; };func();cout << i << endl;return 0;
}