C++11 - 3 - lambda expressions

c++

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:
    1. function:
    2. function pointer:
    3. Functor object:
    4. 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:
    1. [capture list]
    2. (parameter list)
    3. -> return value type
    4. {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:
    1. capture by value
    2. pass-by-reference capture
  • Capture range requirements:
    1. in the same scope as the lambda expression
    2. Can only capture local variables
    3. For the same variable, it is not possible to capture value and capture reference at the same time
  • Capture form:
    1. Quote capture:
      1. Capture a reference to a variable in the current scope:
        &a ->{}
      2. Capture references to all variables in the current scope:
        & ->{}
    2. Capture by value:
      1. Capture the value of a variable in the current scope:
        a ->{}
      2. Capture all variable values ​​​​under the current scope:
        = ->{}

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:
    1. The capture list is converted into a member variable in the class
    2. 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());
};

Guess you like

Origin blog.csdn.net/buptsd/article/details/126883125