Lambda expressions in C + + _c language

Source: Internet
Author: User
Tags modifier mul

I'm a C + +.

Have been reminding myself, I am engaged in C + +; But when c++11 out so long, I did not follow the team go, found very sorry for their identity, but also good, found that they have a period of time did not write C + + code. Today I saw the lambda expression in C + +, although the use of C #, but C + +, has been no use, also do not know how to use, on the poor even the lambda grammar can not understand. OK, here is a simple summary of the lambda in C + +, even if it is an account of their own, I am engaged in C + +, I am a C + + programmer.

A simple code

I am also not a literary person, for the history of the lambda, as well as the Lambda and C + + of the source, I am not very familiar with the technical people, pay attention to the code to say things.

Copy Code code as follows:

#include <iostream>
using namespace Std;

int main ()
{
int a = 1;
int b = 2;

Auto Func = [=, &b] (int c)->int {return b + = a + C;};
return 0;
}

When I first saw this code, I was directly messy, directly do not understand AH. The above code, if you understand, the following content on the review at that time, if you do not understand, then go with me to sum up.

Basic syntax

In simple terms, a lambda function is a function, and its syntax is defined as follows:

Copy Code code as follows:

[Capture] (parameters) mutable->return-type{statement}

1.[capture]: Capture list. The capture list always appears at the beginning of the lambda function. In fact, [] is a lambda derivation. The compiler determines whether the next code is a lambda function based on the derivation. The capture list is able to capture variables in the context for use by the lambda function;

2. (parameters): Parameter list. Consistent with the parameter list of a normal function. If parameter passing is not required, it can be omitted together with the parentheses "()";

3.mutable:mutable modifier. By default, a lambda function is always a const function, and mutable can cancel its constant nature. When using this modifier, 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 we do not need to return the value. In addition, if the return type is clear, the section can also be omitted to allow the compiler to deduce the return type;

5.{statement}: Function body. Content is the same as a normal function, but you can use all of the captured variables in addition to the parameters you can use.

The biggest difference from a normal function is that, in addition to the parameters that can be used, a lambda function can also access data in some contexts by capturing the list. Specifically, the capture list describes which data in the context can be used by a lambda, and how it is used (in a value-passing manner or by reference). Syntactically, the capture list is included in [], and the capture list consists of multiple snap items separated by commas. The capture list has the following forms:

1.[var] Represents a value-passing method for capturing variable var;
2.[=] Represents a variable in which the value is passed to capture all parent scopes (including this);
3.[&var] Represents a reference pass-catch variable var;
4.[&] Represents a variable (including this) that refers to the way in which all parent scopes are captured;
5.[this] Represents the way a value is passed to catch the current this pointer.

This refers to a parent scope, which is a block of statements containing a lambda function, saying that the popular point is the "{}" code block that contains the lambda. The capture list above can also be combined, for example:

1.[=,&a,&b] means to capture variables A and B by reference, and to capture all other variables in a value-passing manner;
2.[&,a,this] means that the variables a and this are captured in a value-passing manner, and the reference is passed to catch all other variables.

It is worth noting, however, that the capture list does not allow variables to be repeatedly passed. The following examples are typical repetitions that result in compile-time errors. For example:

3.[=,a] Here we have captured all the variables by value, but we repeat the catch of a, and the error occurs;
4.[&,&this] Here & has captured all variables by reference, and capturing this is also a repetition.

Use of lambda

For the use of lambda, to tell you the truth, I don't have much to say, personally understand, in C + + before no lambda, we are so good to use, and do not have a lack of lambda C + + have any complaints, and now have lambda expression, just more convenient for us to write code. I do not know if you remember the C + + STL library in The Imitation function object, imitation functions for ordinary functions, an affine function can have an initialization state, which is specified by a parameter when declaring a functor object, and is generally stored in a private variable of an imitation function object; For functions that require a state, we typically do so using an imitation function, such as the following code:

Copy Code code as follows:

#include <iostream>
using namespace Std;

typedef enum
{
Add = 0,
Sub
Mul
Divi
}type;

Class Calc
{
Public
Calc (int x, int y): m_x (x), m_y (y) {}

int operator () (Type I)
{
Switch (i)
{
Case ADD:
return m_x + m_y;
Case SUB:
return m_x-m_y;
Case MUL:
return m_x * M_Y;
Case Divi:
return m_x/m_y;
}
}

Private
int m_x;
int m_y;
};

int main ()
{
Calc Addobj (10, 20);
Cout<<addobj (ADD) <<endl; It was found that the use of the enum type also changed and was more "strong" in c++11
return 0;
}

Now that we have the tool for lambda, is it possible to rewrite the above implementation? Look at the code:

Copy Code code as follows:

#include <iostream>
using namespace Std;

typedef enum
{
Add = 0,
Sub
Mul
Divi
}type;

int main ()
{
int a = 10;
int B = 20;

Auto Func = [=] (Type I)->int {
Switch (i)
{
Case ADD:
return a + B;
Case SUB:
return a-b;
Case MUL:
return a * b;
Case Divi:
return a/b;
}
};

Cout<<func (ADD) <<endl;
}

The obvious effect, the code is simple, you write less code, but also to try C + + lambda expression Bar.

About the wonderful things of the lambda.

Look at this section of code:

Copy Code code as follows:

#include <iostream>
using namespace Std;

int main ()
{
int j = 10;
Auto By_val_lambda = [=]{return j + 1;};
Auto By_ref_lambda = [&]{return j + 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 results of the program output are as follows:

Copy Code code as follows:

By_val_lambda:11
By_ref_lambda:11
By_val_lambda:11
By_ref_lambda:12

Do you have any idea??? Then why is that? Why is the third output not 12?

In By_val_lambda, J is treated as a constant that will not change once it is initialized (it can be thought of as a constant with the same name as J in the parent scope), while in By_ref_lambda, J still uses the value in the parent scope. So, when using a lambda function, if the value that needs to be captured becomes a constant of the lambda function, we usually catch it by value, but instead, if the value that needs to be captured becomes a variable at the time the lambda function is run, it should be captured by reference.

A bit more dizzy code:

Copy Code code as follows:

#include <iostream>
using namespace Std;

int main ()
{
int val = 0;
Auto CONST_VAL_LAMBDA = [=] () {val = 3;}; Wrong!!!

Auto MUTABLE_VAL_LAMBDA = [=] () mutable{val = 3;};
Mutable_val_lambda ();
cout<<val<<endl; 0

Auto CONST_REF_LAMBDA = [Ampersand] () {val = 4;};
Const_ref_lambda ();
cout<<val<<endl; 4

Auto MUTABLE_REF_LAMBDA = [ampersand] () 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 nature. As a rule, a const member function is the value of a non-static member variable that cannot be modified in a function body. For example, the lambda expression above can be considered as the following code of imitation functions:

Copy Code code as follows:

Class Const_val_lambda
{
Public
CONST_VAL_LAMBDA (int v): Val (v) {}
void operator () () const {val = 3;}//Constant member function

Private
int Val;
};

For the const member function, modify the non-static member variable, so there is an error. The way the reference is passed does not change the reference itself, but only changes the referenced value, so there is no error. are some tangled rules. Understand it slowly.

Summarize

For a lambda this kind of thing, some people use is very cool, but some people are not happy to look at. The beholder, the benevolent. In any case, you, as a programmer, will. This article is used to make up for the lack of awareness of the C + + lambda expression of the fault, lest in the future in other people's code to see the lambda, still do not understand this kind of thing, then lose the adult.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.