C++11 New Characteristics--lambda

Source: Internet
Author: User
Tags arithmetic visual studio 2010

Generate random numbers

Let's say we have a vector<int> container that wants to initialize it with a random number less than 100, one of which is generated by the Generate function, as shown in code 1. The Generate function accepts three arguments, the first two parameters specify the starting and ending positions of the container, and the second parameter specifies the build logic, which is expressed through a lambda.

Code 1

We now see that the lambda is the simplest form, containing only the capturing clause and the function body two necessary parts, the rest being omitted. [] is the capturing clause of the lambda and the syntax that leads to the lambda, and when the compiler sees the symbol, it knows we're writing a lambda. The function body is surrounded by {}, and the code inside is no different from the function body of a normal function.

So, how many odd numbers are there in the random number generated by code 1, we can count by the For_each function, as shown in code 3. Unlike the Generate function, the For_each function requires that the lambda we provide accept an argument. In general, if the parameter list of a lambda contains no arguments, we can omit it, as shown in code 1, and if you have multiple arguments, you can separate them by commas, such as (int index, std::string item).

Code 2

Seeing here, attentive readers may have found a "&odd_count" in the capture clause of code 2, which is what to do. We know that the key part of this code is to modify an external count variable in the function body of the lambda, and the common language (such as C #) automatically captures all the variables of the current context for the lambda, but C + + requires that we explicitly specify the variable to be captured in the capture clause of the lambda. Otherwise, you cannot use these variables in the function body. If nothing is written in the capture clause, as shown in code 1, the compiler will assume that we do not need to capture any variables.

In addition to explicitly specifying the variables that you want to capture, C + + requires us to specify how these variables are passed, and there are two ways in which you can choose between passing by value and passing by reference. This type of writing, like [&odd_count], is passed by reference, which allows you to modify the Odd_count variable in the function body of the lambda. In contrast, if the variable name is not preceded by a "&" that is passed by value, these variables are read-only in the function body of the lambda.

If you want to pass all the variables that capture the current context by reference, you can write the capture clause [&]; if you want to pass all the variables that capture the current context by value, you can write the capture clause [=]. If you want to pass by reference as the default delivery method, also specifies that individual variables are passed by value, which can be written as [Ampersand, A, b]; If the default pass is passed by value, and the individual variables are passed by reference, the capture clause can be written [=, &a, &b]. It is worth reminding that the like [Ampersand, A, &b] and [=, &a, b] These are invalid, because the default mode of delivery has been covered B variables, no need to specify, the effective writing should be [Ampersand, a] and [=, &a].

Generate Arithmetic progression

Now let's change the first question and generate a arithmetic progression with a first item of 0 and a tolerance of 2 through the Generate function. With the previous knowledge of the capture clause, it is easy to think of code 3, which first passes the capture I variable, then modifies its value in the function body of the lambda and returns it to the Generate function.

Code 3

If we change the transfer of the I variable by value and then add the mutable declaration after the capture clause, as shown in code 4, we can get the same effect, I mean the output. So, what's different about these two schemes? After you call the Generate function, check the value of the I variable to find the answer. It should be explained that if we add the mutable declaration, the argument list cannot be omitted, even if it contains no parameters.

Code 4

Using code 3, the value of the I variable is 18 after calling the Generate function, and using code 4, the value of the I variable is-2. This means that the mutable declaration allows us to modify variables passed by value in the function body of the lambda, but these modifications are not visible to the world outside of the lambda, and interestingly, these modifications are shared between multiple invocations of the lambda. In other words, the Generate function of code 4 calls 10 lambda, and the result of the modification of the I variable at the time of the previous call can be accessed at the last call.

It sounds like there is an object, the I variable is its member field, and the lambda is its member function, in fact, the lambda is the syntactic sugar of the function object, and the lambda of code 4 will eventually be converted to the functor class shown in code 5.

Code 5

You can also replace the lambda of code 4 with the functor class, as shown in code 6.

Code 6

How to declare the type of a lambda.

So far, we have passed the lambda as a parameter directly to the function, and if we want to pass a lambda to multiple functions, or call it multiple times as a function, then consider saving it to a variable, and the question is how the variable should be declared. If you really don't know, don't want to know, the easiest way to do that is to give it to the compiler, as shown in code 7, where the Auto keyword is equivalent to C # 's Var, and the compiler infers its actual type based on the value we use to initialize the F1 variable, which is static and completes at compile time.

Code 7

If we want to define a function that accepts the lambda of code 7 as a parameter, then how is the type of the argument written? We can declare it as a function template type, as shown in code 8, where the type parameter reflects the signature of the lambda--two int parameters, and an int returns the value.

Code 8

Alternatively, you can declare this function as a template function, as shown in code 9.

Code 9

No matter how you declare the function, the call is the same, and they all accept the lambda or function object as arguments, as shown in code 10.

Code 10

When the value of the capture variable is determined.

Now, I'm going to adjust the lambda code 7 as shown in code 11, to provide input by capturing clauses instead of argument lists, which use different ways of passing, and if I modify the values of these two parameters in the third row, it will affect the call on line fourth.

Code 11

If you run code 11, you will see that the output is 5. Why. This is because by value the value of the variable has been determined at the moment the declaration of the Lambda is made, no matter how it is modified outside, it can only access the version that was passed in the Declaration; So any modifications outside the call to the lambda are visible inside. This problem is not in C #, because C # only passes this way by reference.

When the type of the return value can be omitted.

Finally, we have not mentioned the type of return value, and the compiler will always help us infer it automatically. No, there are only two situations where you can omit the return value type when declaring a lambda, and the previous example just satisfies both, so it's only now that the function body contains a return statement, as shown in the original code 1. The lambda does not return a value, as shown in code 2.

When you need to add a return value type, you must put it behind the argument list, and precede the return value type with the "->" symbol, as shown in code 12.

Code 12

* The above code is tested and passed on Visual Studio 2010 and Visual Studio RC.

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.