Program Optimization Based on C ++ Lambda expressions

Source: Internet
Author: User
Tags visual studio 2010
Program Optimization Based on C ++ Lambda expressions

This is a little story about C \ C ++ programmers, about C ++ 11-a new standard just passed...

Do not get me wrong. The "optimization" mentioned in the question is not about improving program performance-Lambda expressions cannot do this. In essence, it is just a "syntactic Sugar. Without this expression, we can still write programs that meet the requirements. Just like giving up C and using assembly, or giving up assembly and using machine language, the scope you can control is there without increasing or decreasing. But if you have a choice, I believe most people will choose Assembly rather than machine language, C rather than assembly, or even C ++ rather than C ....... If you do, I have a reason to believe that you will choose the Lambda expression in the new C ++ standard because it can simplify your program, it makes it easier for you to write programs. It makes your programs easier to read and more elegant. It also gives you more capital to show off to your peers.

Starting from a practical application

Let's look at an example.

Whether you are a C language user or a C ++ user, if you are engaged in algorithm development for PC programs, I believe that you may have used the C ++ standard template library STL (string, vector, and so on ). After all, STL is a good abstraction, and it does not need to be white. Is it true. There is a major category of algorithms in STL. the abstraction of these algorithms is equally good. Let's talk about the Sorting Algorithm (sort.

Suppose there is a structure called Student, which contains two items: ID and name, indicating the Student ID and name respectively. In an application, you want to sort the Student array by ID from large to small, the program may be written as follows (all programs in this article are compiled under Visual Studio 2010 ):
# Include <string>
# Include <vector>
# Include <iostream>
# Include <iterator>
# Include <algorithm>
Using namespace std;

Struct Student {
Unsigned ID;
String name;
Student (unsigned I, string n): ID (I), name (n ){}
};

Struct compareID {
Bool operator () (const Student & val1, const Student & val2 )? ??? Const {
Return val1.ID <val2.ID;
}
};

Int main (int argc, char * argv []) {
Student a [] = {Student (2, "John"), Student (0, "Tom"), Student (1, "Lily ")};
Sort (a, a + 3, compareID ());
For (int I = 0; I <3; ++ I)
Cout <a [I]. ID <''<a [I]. name <endl;
Return 0
}

The program uses sort for sorting, and then outputs the result using a for loop. This sorting can be completed because of the existence of the imitation function compardID.

Now, if the user's needs have changed (or another requirement) and you need to sort by the student's name, you need to re-write an imitation function as follows:

Struct compareName {

Bool operator () (const student & val1, const student & val2) const? ? {
Return val1.name <val2.name;
}
};

Then modify the sort call:

Sort (A, A + 3, comparename ());

The problem arises. Do you realize it? You just want to express a simple sorting method, and you have to introduce a lot of code lines to build the corresponding function. If this function is used in many places, the value of building it is relatively large. If it is used only in one place, you also have to write so many lines of code while being fluent. On the other hand, when the reader of the program reads the corresponding part, he also has to make smooth thinking in the middle. He is struggling somewhere in the project-how does comparename or compareid work?
Yes, yes. As a C ++ veteran, you will say that writing code is too unprofessional. There is no way to create a function like this. For example, when sorting by ID, you can introduce the bind in the boost library. For example:

Sort (A, A + 3, BIND (less <unsigned> (), BIND (& Student: ID, _ 1), BIND (& Student: ID, _ 2 )));

If you can write or read this code, I admit that your c ++ level is indeed justified (if you do not understand it, it doesn't matter, it is not the focus of this Article ). But is this code really good? Indeed, this can omit the imitation function. But the problem is that the complexity of the Code is greatly increased-even if it is a simple requirement, the bind expression must be as complex as it is. What complicated form should be written for a more complex requirement, this is a torment for the bind itself, the program writer and the reader-do you hold it?

If lambda expressions are used, well, this sort statement can be written as follows:

Sort (a, a + 3, [] (const Student & val1, const Student & val2) {return val1.ID <val2.ID ;});

That seems a bit strange. The third function of sort is a Lambda expression. If we do not look at the beginning of "[]", the following part is like a function-you can easily see what this function is doing: Given two Student elements, compare the ID values of the two elements and return the comparison result-this is much easier to read than the bind result above.

In fact, using Lambda expressions, the above program can be modified as follows (only the main function is listed ):

Int main (int argc, char * argv []) {
Student a [] = {Student (2, "John"), Student (0, "Tom"), Student (1, "Lily ")};
Sort (a, a + 3, [] (const Student & val1, const Student & val2) {return val1.ID <val2.ID ;});
For_each (a, a + 3, [] (const Student & val) {cout <val. ID <''<val. name <endl ;});
Return 0
}

The for_each clause is used for output-the Lambda expression in the clause means that the ID and Name values are output for each val-which saves the for loop.

Lambda expressions are introduced to facilitate program writing and easier reading. Like STL, why not use it?

Basic Syntax of Lambda expressions

With a perceptual knowledge, let's analyze the syntax of Lambda expressions.

I have no intention of translating the Lambda expression chapter in the C ++ standard draft here (I am not doing this either ). I just want to explain its syntax in the most popular way here. In terms of structure, Lambda expressions can be written as follows:

Lambda-introducer lambda-declarator (opt) compound-statement

Lambda-introducer is the "[]" That we just mentioned. It cannot be omitted. Variables may also appear in brackets. The local variable is passed into the Lambda expression. Lambda-declaratoropt is optional, including the expression parameter list, return value information, mutable Declaration (and other information, which will not be discussed here ). The final compound-statement is the main content of the expression.

Let's look at an example:

Int n = 10;
[N] (int k) mutable-> int {return k + n ;};

The second line of the program is a lambda expression, with almost all the things that can appear in lambda (of course, as I mentioned earlier, some other information is not discussed here, ). Let's analyze the content one by one:

L [n] is Lambda-introducer, and n is a variable, indicating that variable n in the scope of the expression will be passed into this expression. In this example, the input value is 10. Lambda-introducer can specify a variable to be passed in as a value, or specify it as a reference in other forms. Let's talk about its variants through baidu.

L (int k) indicates the parameter list, which is part of lambda-declarator. You can think of an expression as an imitation function (for example, the above ). The parameter list of the imitation function is specified here. If the function parameter list is empty, this part can be omitted.

Lmutable indicates whether the variables in the imitation function can be changed. In the previous article, the compareID function is used as an example. It is noted that the operator () is const. If this mutable is introduced in the lambda expression, the operator () definition in the corresponding imitation function does not include this const-this means that the variable value in the imitation function (Lambda-introducer passed in) it can be changed. The difference between operator () const and operator () is beyond the scope of this article. For more information, see the relevant C ++ tutorials.

L-> int indicates the return type (int here ). If the compiler can deduce the return type from the Code, or the return type of the Lambda expression is void, this item can be omitted;

L {return k + n;} is the compound-statement: function body.

Through analysis, we can see that this Lambda expression is equivalent to a function. This function reads an int value k and adds n to the value to return. According to the preceding instructions, this expression can be abbreviated:

[N] (int k) {return k + n ;};

Lambda expressions can be stored in std: function <T> or std: reference_closure <T> type variables. T indicates the type of the function corresponding to the expression. The above expression is used as an example. If the input parameter is an int variable and the output is an int, you can write it as follows to save it:

Function <int (int)> g = [n] (int k) {return k + n ;};

In another example, the Lambda expression used previously:

[] (Const Student & val1, const Student & val2) {return val1.ID <val2.ID ;}

It can be stored in function <bool (constStudent &, constStudent &)> variables of this type.

If you are too difficult to write, you can also use another new feature in the new C ++ standard: Type derivation. Auto is used as the variable type, so that the compiler can deduce the expression type by itself:

Auto g = [n] (int k) {return k + n ;};

No problem. Writing g is still a strongly typed variable, but its type is derived by the compiler. The advantage is that you do not need to write too long variable types.

Lambda expressions advanced

At the end, let's look at some advanced usage of C ++ Lambda expressions.

Lambda expressions are introduced mainly for functional programming. With Lambda expressions, we can also do some functional programming. For example, an application that uses a function as the return value:

Auto g = [] (int n)-> function <void (int)> {
Return [n] (int k) {cout <n + k <'';};
};

It is a Lambda expression that inputs an integer Variable n and returns a function (lambda expression). This function receives an int value k and prints k + n. G is used as follows:

Int a [] = {1, 2, 4, 5, 6, 7, 8, 9, 0 };
Function <void (int)> f = g (2 );
For_each (a, a + 10, f );

It will output: 3 4 5 6 7 8 9 10 11 2

A little Functional Programming taste J

For other things, such as the following expression:

[] () {} ();

Is a valid call. "[] () {}" Indicates a Lambda expression. The input parameter is null and void is returned. The final () indicates the call of the value-although nothing is done, the compilation can be passed, which is very annoying.

Well, write it here. The last thing about Lambda expressions is that it is defined in the new Standard C ++ 11. The old compiler does not support it (this is why I use VS2010 ). Do you want to use it and the benefits of other new standards? Hey, your guy (the compiler) should have upgraded J.

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.