Original address: lambda expression in C + +
Jelly want
Always remind myself that I am a C + +, but when c++11 out so long, I did not follow the team, found that I am sorry for their identity, but also fortunately, found themselves also have a period of time did not write C + + code. Today I saw the lambda expression in C + +, although using C #, but C + +, has been no use, and do not know how to use, poor even the lambda grammar can not understand. Okay, here's a simple summary of the lambda in C + +, even if it's an account of myself, I'm in C + +, I'm a C + + programmer.
A simple code
I am not a literary person, for the history of lambda, and the source of Lambda and C + +, I am not very familiar with the technical people, pay attention to take the code to say things.
#include <iostream>usingnamespaceint main () { int 1 ; int 2 ; = [=, &b] (int c),int {return B + = a + c;} ; return 0 ;}
when I first saw this piece of code, I was directly messy, I could not understand it directly. The above code, if you understand, the following content is reviewed at that time; If you do not understand, then you can summarize with me.
Basic syntax
To put it simply, a lambda function is a function whose syntax is defined as follows:
[capture] (parametersmutable ,return-type{statement}
1,[capture]: Capture list. The capture list always appears at the beginning of the lambda function. In fact, [] is a lambda balloon. The compiler determines whether the next code is a lambda function according to the balloon. The capture list captures variables in the context for use by the lambda function;
2, (Parameters): Parameter list. is consistent with the argument list of the normal function. If parameter passing is not required, it can be omitted together with parentheses "()";
3, mutable:mutable modifier. By default, a lambda function is always a const function, and mutable can cancel its constant behavior. When the modifier is used, the argument list cannot be omitted (even if the argument is empty);
4,->return-type: return type. Declares the return type of a function in the form of a trace return type. We can also omit the symbol "--" when no return value is required. In addition, if the return type is explicit, you can omit the part and let the compiler deduce the return type;
5, {statement}: function body. The content is the same as a normal function, but you can use all the captured variables in addition to the parameters you can use.
The biggest difference from normal functions is that, in addition to using parameters, lambda functions can access data in some contexts through a capture list. Specifically, the capture list describes what data in the context can be used by lambda, and how it is used (in the way that values are passed or referenced). Syntactically, the "[]" is included in the capture list, and the snap list consists of multiple snap items, separated by commas. The capture list has several forms:
- [Var] means that the value is passed in the way of capturing variable var;
- [=] indicates that the value is passed in a variable that captures all parent scopes (including this);
- [&var] indicates that the reference passes the catch variable var;
- [&] represents a variable (including this) that captures all parent scopes by means of a reference pass;
- [This] indicates how the value is passed to capture the current this pointer.
It mentions a parent scope, which is a block of statements that contains a lambda function, saying that popular points are "{}" blocks of code that contain lambda. The above snap list can also be combined, for example:
- [=,&a,&b] means capturing variables A and b in the way of reference passing, capturing all other variables in a value-passing manner;
- [&,a,this] means that the variable A and this are captured in a value pass, and the reference is passed to catch all other variables.
It is worth noting, however, that the catch list does not allow variables to be passed repeatedly. The following examples are typical repetitions that lead to compile-time errors. For example:
- [=,a] Here has been the value of the way to capture all variables, but repeatedly catch a, will be error;
- [&,&this] Here & has captured all variables in a reference pass, and capturing this is also a repetition.
Use of lambda
For the use of lambda, to be honest, I do not have much to say, personally understand, in the absence of Lambda before the C + +, we are so good use, and there is no lack of lambda C + + have any complaints, and now have a lambda expression, just more convenient for us to write code. Do not know whether you remember the C + + STL Library of the functor, the functor to the normal function, the functor can have the initialization state, and these initialization state is declared as a functor object, by the parameters specified by the parameter, is usually stored in the private variables of the functor object; in C + +, For functions that require States, we typically do this using an imitation function, such as the following code:
1#include <iostream>2 using namespacestd;3 4typedefenum5 {6Add =0,7 Sub,8 Mul,9 diviTen }type; One A classCalc - { - Public: theCalc (intXinty): m_x (x), m_y (y) {} - - int operator() (Type I) - { + Switch(i) - { + CaseAdd: A returnM_x +m_y; at CaseSub: - returnM_x-m_y; - CaseMul: - returnM_x *m_y; - Casedivi: - returnM_x/m_y; in } - } to + Private: - intm_x; the intm_y; * }; $ Panax Notoginseng intMain () - { theCalc Addobj (Ten, -); +Cout<<addobj (ADD) <<endl;//found in c++11, the use of enum type has changed, more "strong" A return 0; the}
View Code
Now that we have a lambda tool, is it possible to rewrite the implementation above? Look at the code:
1#include <iostream>2 using namespacestd;3 4typedefenum5 { 6Add =0,7 Sub,8 Mul,9 diviTen }type; One A intMain () - { - intA =Ten; the intb = -; - -Auto Func = [=] (Type I)int { - Switch(i) + { - CaseAdd: + returnA +b; A CaseSub: at returnAb; - CaseMul: - returnAb; - Casedivi: - returnAb; - } in }; - toCout<<func (ADD) <<Endl; +}
View Code
the obvious effect, the code is simple, you also write less code, but also to try the lambda expression in C + +.
About Lambda, those wonderful things.
Look at the following section of code:
#include <iostream>using namespacestd; intMain () {intj =Ten; Auto By_val_lambda= [=]{returnJ +1; }; Auto By_ref_lambda= [&]{returnJ +1; }; cout<<"By_val_lambda:"<<by_val_lambda () <<Endl; cout<<"By_ref_lambda:"<<by_ref_lambda () <<Endl; ++J; cout<<"By_val_lambda:"<<by_val_lambda () <<Endl; cout<<"By_ref_lambda:"<<by_ref_lambda () <<Endl; return 0; }
The program output results are as follows:
one byone
do you have any idea??? Then why is this? Why is a third output not 12?
In By_val_lambda, J is treated as a constant that, once initialized, is not changed (it can be thought of as a constant with the same name as the J in the parent scope), while in By_ref_lambda, J still uses the value from the parent scope. So, when using a lambda function, if the value that needs to be captured becomes a constant of a lambda function, we usually use the method of passing by value, and conversely, if you need to capture a value that becomes a variable that the lambda function is running, you should catch it by reference.
Let's get a more dizzy code:
#include <iostream>using namespacestd; intMain () {intval =0; //Auto Const_val_lambda = [=] () {val = 3;}; wrong!!!Auto Mutable_val_lambda= [=] () mutable{val =3; }; Mutable_val_lambda (); cout<<val<<endl;//0Auto Const_ref_lambda= [&] () {val =4; }; Const_ref_lambda (); cout<<val<<endl;//4Auto Mutable_ref_lambda= [&] () mutable{val =5; }; Mutable_ref_lambda (); cout<<val<<endl;//5 return 0; }
This code is primarily used to understand the mutable keyword in a lambda expression. By default, a lambda function is always a const function, and mutable can cancel its constant behavior. As a rule, a const member function is not able to modify the value of a non-static member variable within a function body. For example, the lambda expression above can be considered as the following functor code:
class const_val_lambda{public: const_val_lambda (int v): Val (v) {} void operator Const 3 // Constant member functions Private : int Val;};
for const member functions, modify non-static member variables, so there is an error. The way the reference is passed does not change the reference itself, but only the value of the reference, so there is no error. Are some of the tangled rules. Understand it slowly.
Summarize
For the lambda thing, some people use very cool, and some people do not look at the unpleasant. The benevolent see of the beholder. In any case, you, as a programmer, will. This article is used to make up for the C + + lambda expression of the wrong cognition, lest later in the code of others to see the lambda, still do not understand this kind of thing, then lose the adult.
Go Lambda expressions in C + +