lambda expressions in C++11

 Lambda expressions originate from the concept of functional programming, which can define the target function or function object anonymously in place, without writing an additional named function or function object. The type of lambda expression is called "closure type" in C++11, which can also be understood as a functor (with operator() class), and its syntax is as follows:

  [capture] (params) opt -> ret {body;};

  capture: capture list;

  params: parameter list;

  opt: function options;

  ret: return value type;

  body: The body of the function.

  In many cases, the return value of a lambda expression is very obvious. In C++11, it is allowed to omit the return value definition of a lambda expression, that is, remove the "->ret" part, so that the compiler will automatically deduce the return value type. A simple lambda expression is as follows:  

#include "stdafx.h"
#include<iostream>// std::cout

intmain()
{
    auto f = [](int a, int b) -> int {return (a*b); };
    std::cout << f(3, 4) << std::endl; // output:12

    return 0;
}

 The capture field in a lambda expression is very useful. Capture means to capture the external variable used inside the lambda function body . There are several different capture methods:

  []: Do not capture any external variables, if you use external variables in the function body, an error will be reported;

  [&]: Capture all external variables by reference. If the value of the external variable is changed in the function body, the value of the external variable will change accordingly;

  [=]: Capture all external variables by value. If the "external variable value" is changed in the function body, the external variable value will not change;

  [=, &foo]: captures all external variables by value , and captures the foo variable by reference;

  [bar]: Capture the bar variable by value, other external variables are not captured;

  [this]: Capture the this pointer in the current class, so that the lambda expression has the same access rights as the current class member function. If & or = has been used, this is added by default.

  Note the difference between capture by value and capture by reference. Capture by value copies the external variables used in the lambda expression and saves it to the lambda closure type. If the external variables used are later modified, The variable used in the lambda expression will not change, because the variable is only a copy; capture by reference is to directly read or operate on the value of the variable, as shown in the code:

#include "stdafx.h"
#include<iostream>// std::cout

intmain()
{
    int numA = 0;
    int numB = 0;
    {
        auto f1 = [] {return numA; };// error, no external variable captured
        auto f2 = [&numB] {return (--numB); };
        f2();
        std::cout << numB << std::endl;// -1
    }

    int numC = 100;
    int numD = 100;
    auto f3 = [=]() -> int {return (numC*numD); };
    numD = 99;
    std::cout << f3() << std::endl; // output:10000

    return 0;
}
有了lambda表达式,我们在使用for循环或者std::for_each的时候,就可以改写成如下形式:
#include "stdafx.h"
#include<iostream>// std::cout
#include<list>
#include <algorithm>
int main()
{
    std::list<int> l = { 1, 3, 5, 87, 64, 33, 0, -1, -100};
    int nCount = 0;
    std::for_each(l.begin(), l.end(), [&nCount](int val) {if (val > 50) nCount++; });
    std::cout << "The number larger than 50 in l is: " << nCount << std::endl;

    return 0;
}
总结一下,lambda表达式看起来和Java里边的匿名函数比较像,使用lambda表达式后,可以使程序变得非常简洁。但是,如果使用的lambda表达式包含的内容过多,或者lambda表达式的实体是好多地方都会用到的功能性函数,还是单独列出一个函数比较方便。


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325662601&siteId=291194637