C++11 - lambda expressions
Foreword:
Vue框架:
OJ算法系列:
Learn Vue magic tricks from the project - algorithm detailed explanation
Linux操作系统:
Fenghou Qimen - linux
callable object:
- Meaning: an object with the functions of passing in parameters, processing them, and passing out results
- Classification:
- function:
- function pointer:
- Functor object:
- lambda expression:
- Example:
//1, 函数:
void fmin(int x, int y){
return x<y?x:y;
}
//2,函数指针:
void func(int, int) = fmin();
func(1, 2);
//3,仿函数对象:
struct IntLess{
bool operator()(int &x, int &y){
return x<y?x:y;
}
}
IntLess(1, 2);
//4,简易lambda表达式:
auto function = [](int x, int y){
return x<y?x:y;
};
function(1, 2);
lambda expression:
Format:
- Can be composed of two/three/four/five parts:
//附加说明的五部分:附加关键词一般为mutable、noexcept
auto func = [](int x, int y)mutable->int{
return x<y?x:y;
}
//完整的四部分:
auto func1 = [](int x, int y)->int{
return x<y?x:y;
};
//省略返回类型,可自动推导返回类型
auto func2 = [](int x, int y){
return x<y?x:y;
};
//当不需要参数时候,可省略参数
auto func3 = []{
cout<< "hello world"<< endl;
};
- Complete four parts:
- [capture list]
- (parameter list)
- -> return value type
- {function body}
- Additional Part: Additional Keywords
- The two parts required for lambda expressions: []{}
The two parts that can be omitted: ()->
Catch list:
- Meaning: When passing parameters to lambda expressions, only values can be passed in (), and when you want to pass references or addresses, you need to use the capture list
- Function: Capture local variables in the same scope as the lambda expression
- Capture form:
- capture by value
- pass-by-reference capture
- Capture range requirements:
- in the same scope as the lambda expression
- Can only capture local variables
- For the same variable, it is not possible to capture value and capture reference at the same time
- Capture form:
Additional keywords:
- mutable keyword:
1. Function: The variable obtained by value capture is const by default . If you want to write it, you need to add the attachment keyword mutable
2. Placement: add it directly after (formal parameter), that is, use Mutable keyword must be added (formal parameter list) - Example:
//报错:常量不可修改
int main(){
int x = 0;
auto func = [=](){
x++;
cout<<x<<endl;
};
cout<<x<<endl;
}
//()mutable
int main(){
int x = 0;
auto func = [=]()mutable{
x++;
cout<<x<<endl;
};
cout<<x<<endl;
}
The essence of the decltype expression:
- Lambda expressions are essentially functor classes
- Just like the essence of the range for is an iterator
- C++11 also provides us with an operator symbol for inferring variable types: decltype
auto func = [](int x, int y){
return x<y?x:y;
};
cout<< decltype(func).name();
-
The difference between decltype and auto:
1. decltype is used when a variable type needs to be declared, such as a function parameter
2. auto is used when a variable type does not need to be declared, such as simply using -
decltype uses:
auto func1 = []{
cout<<"极简lambda"<<endl;};
auto func2 = func1;
decltype(func1) func3 = func1;
Comparison of capture list and parameter list:
substance:
- Lambda expressions are transformed into functor classes:
- The capture list is converted into a member variable in the class
- The parameter is converted to an inner function parameter
scope:
- Formal parameter list () + mutable, the source of the parameter can be any variable , of course, the scope of the mutable is not added, and the write permission disappears
- The objects captured by the capture list can only be local variables in the same scope
- When operating on local variables in the same scope, ()+mutable and [] have the same effect
Call object comparison:
lambda:
-
Lambda expressions are faster to write than functions/function pointers/functor objects,
Suitable for writing codes that sort objects of a class based on different fields of a class, similar to this
-
Given below is a product class, and ask to sort the product objects according to the price/rating/name of the product:
-
Commodity category:
class Goods{
private:
int price;
double evaluate;
char* name;
public:
//八大默认函数,自动补全。
Goods(int _price, double _evaluete, char* _name){
price = _price;
evaluete = _evaluete;
name = _name;
}
};
- Commodity sorting - based on lambda expressions:
vector<Goods> v{
{
1, 1.0, "a"}, {
2, 2.0, "b"}, {
3, 3.0, "c"}, {
4, 4.0, "d"}};
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
return a.price > b.price;
});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
return a.price < b.price;
});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
return a.evaluete > b.evaluete;
});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
return a.evaluete < b.evaluete;
});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
return strcmp(a.name, b.name);
});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
return -1*strcmp(a.name, b.name);
});
function pointer:
- Item sorting - based on functions/function pointers:
bool ComparePriceLess(Goods &a, Goods &b){
return a.price < b.price;
}
bool ComparePriceMore(Goods &a, Goods &b){
return a.price < b.price;
}
bool CompareEvaluateLess(Goods &a, Goods &b){
return a.price < b.price;
}
bool CompareEvaluateMore(Goods &a, Goods &b){
return a.price < b.price;
}
bool CompareNameLess(Goods &a, Goods &b){
return a.price < b.price;
}
bool CompareNameMore(Goods &a, Goods &b){
return a.price < b.price;
}
vector<Goods> v{
{
1, 1.0, "a"}, {
2, 2.0, "b"}, {
3, 3.0, "c"}, {
4, 4.0, "d"}};
sort(v.begin(), v.end(), ComparePriceLess);
sort(v.begin(), v.end(), ComparePriceMore);
sort(v.begin(), v.end(), CompareEvaluateLess);
sort(v.begin(), v.end(), CompareEvaluateMore);
sort(v.begin(), v.end(), CompareNameLess);
sort(v.begin(), v.end(), CompareNameMore);
}
Functor object:
- Item sorting - functor based:
struct ComparePriceLess{
bool operator()(Goods &a, Goods &b){
return a.price < b.price;
}
};
struct ComparePriceMore){
bool operator()(Goods &a, Goods &b){
return a.price > b.price;
}
};
struct CompareEvaluateLess{
bool operator()(Goods &a, Goods &b){
return a.evaluate < b.evaluate;
}
};
struct CompareEvaluateLess{
bool operator()(Goods &a, Goods &b){
return a.evaluate > b.evaluate;
}
};
struct CompareNameLess{
bool operator()(Goods &a, Goods &b){
return -1*strcmp(a.name, b.name);
}
};
struct CompareNameLess{
bool operator()(Goods &a, Goods &b){
return strcmp(a.name, b.name);
}
};
vector<Goods> v{
{
1, 1.0, "a"}, {
2, 2.0, "b"}, {
3, 3.0, "c"}, {
4, 4.0, "d"}};
sort(v.begin(), v.end(), ComparePriceLess());
sort(v.begin(), v.end(), ComparePriceMore());
sort(v.begin(), v.end(), CompareEvaluateLess());
sort(v.begin(), v.end(), CompareEvaluateMore());
sort(v.begin(), v.end(), CompareNameLess());
sort(v.begin(), v.end(), CompareNameMore());
};