C++学习:lambda表达式入门

引言:lambda表达式在STL应用中可以让我们起到十分便捷的功能,我们看下微软的解释。

When you write code, you probably use function pointers and function objects to solve problems and perform calculations, especially when you use STL algorithms. Function pointers and function objects have advantages and disadvantages—for example, function pointers have minimal syntactic overhead but do not retain state within a scope, and function objects can maintain state but require the syntactic overhead of a class definition.

A lambda combines the benefits of function pointers and function objects and avoids their disadvantages. Like a function objects, a lambda is flexible and can maintain state, but unlike a function object, its compact syntax doesn‘t require a class definition. By using lambdas, you can write code that‘s less cumbersome and less prone to errors than the code for an equivalent function obj。

当我们写代码的时候,可以使用函数指针或者函数对象去解决问题和计算,尤其在使用STL的内置算法时,不过函数指针都有明显的优劣势,举个例子,函数指针有简洁的语法但是(不包含状态一定范围内),函数对象是包含状态,但是需要专门去定义一个类并重载函数调用操作符。

This illustration maps the grammar to an example:

  1. lambda-introducer (Also known as the capture clause)&捕获全部  &para 捕获特定参数 =copy
  2. lambda declarator (Also known as the parameter list)输入参数
  3. mutable (Also known as the mutable specification) 是否可以修改 const属性的参数
  4. exception-specification (Also known as the exception specification) 异常
  5. trailing-return-type (Also known as the return type) 返回值类型
  6. compound-statement (Also known as the lambda body) 函数体

下面引入两个例子,看一下lambda表达式带来的好处,两个的demo实现的是相同的功能;

1.利用函数对象实现,必须要定义一个类并重载call-function符号

 1 // even_functor.cpp
 2 // compile with: /EHsc
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 using namespace std;
 7
 8 class FunctorClass
 9 {
10 public:
11     // The required constructor for this example.
12     explicit FunctorClass(int& evenCount)
13         : m_evenCount(evenCount) { }
14
15     // The function-call operator prints whether the number is
16     // even or odd. If the number is even, this method updates
17     // the counter.
18     void operator()(int n) const {
19         cout << n;
20
21         if (n % 2 == 0) {
22             cout << " is even " << endl;
23             ++m_evenCount;
24         } else {
25             cout << " is odd " << endl;
26         }
27     }
28
29 private:
30     // Default assignment operator to silence warning C4512.
31     FunctorClass& operator=(const FunctorClass&);
32
33     int& m_evenCount; // the number of even variables in the vector.
34 };
35
36
37 int main()
38 {
39     // Create a vector object that contains 10 elements.
40     vector<int> v;
41     for (int i = 1; i < 10; ++i) {
42         v.push_back(i);
43     }
44
45     // Count the number of even numbers in the vector by
46     // using the for_each function and a function object.
47     int evenCount = 0;
48     for_each(v.begin(), v.end(), FunctorClass(evenCount));
49
50     // Print the count of even numbers to the console.
51     cout << "There are " << evenCount
52         << " even numbers in the vector." << endl;
53 }
输出:1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 4 even numbers in the vector

看看简洁的lambda表达式如何实现同样的功能。
 1 // even_lambda.cpp
 2 // compile with: cl /EHsc /nologo /W4 /MTd
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 using namespace std;
 7
 8 int main()
 9 {
10    // Create a vector object that contains 10 elements.
11    vector<int> v;
12    for (int i = 1; i < 10; ++i) {
13       v.push_back(i);
14    }
15
16    // Count the number of even numbers in the vector by
17    // using the for_each function and a lambda.
18    int evenCount = 0;
19    for_each(v.begin(), v.end(), [&evenCount] (int n) {
20       cout << n;
21       if (n % 2 == 0) {
22          cout << " is even " << endl;
23          ++evenCount;
24       } else {
25          cout << " is odd " << endl;
26       }
27    });
28
29    // Print the count of even numbers to the console.
30    cout << "There are " << evenCount
31         << " even numbers in the vector." << endl;
32 }

Output:

1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 4 even numbers in the vector.

Summery:看得出lambda表达式代码的好处十分的明显,使代码变得简洁,语义变的清晰。代码不易膨胀,出bug的概率也变小了。下面我们介绍下lambda最基本的语法

Caputre的规则
struct S { void f(int i); };

void S::f(int i) {
    [&, i]{};    // OK
    [&, &i]{};   // ERROR: i preceded by & when & is the default
    [=, this]{}; // ERROR: this when = is the default
    [i, i]{};    // ERROR: i repeated
}

上下文的capurue要注意一些规则, [&]是获取全部reference而不是单个变量的reference, [&para]才是获取单个变量的reference,

=同理,只不过是上下文全部以copy的方式进行传递。

lambda :body的规则

// captures_lambda_expression.cpp
// compile with: /W4 /EHsc
#include <iostream>
using namespace std;

int main()
{
   int m = 0;
   int n = 0;
   [&, n] (int a) mutable { m = ++n + a; }(4);
   cout << m << endl << n << endl;
}
lambda表达式的body中可以包含方法或者函数,而这些函数是可以访问lambda所captrue的变量的。

The body of both an ordinary function and a lambda expression can access these kinds of variables:

  • Parameters
  • Locally-declared variables
  • Class data members, when declared inside a class and this is captured
  • Any variable that has static storage duration—for example, global variables
以上4中变量都是可以访问的。

In addition, a lambda expression can access variables that it captures from the enclosing scope. A variable is explicitly captured if it appears in the capture clause of the lambda expression. Otherwise, the variable is implicitly captured. The body of the lambda expression uses the default capture mode to access variables that are implicitly captured.

The following example contains a lambda expression that explicitly captures the variable n by value and implicitly captures the variable m by reference:

值得注意的是,lambda表达式可以访问不同的变量从captures,一个变量可以显式的从捕获中获取,或者通过隐式捕获,body中可以使用默认的捕获方式去访问隐式捕获的变量

下面这个例子就是看到显式的捕获n,和隐式的捕获m的引用。
 1 // captures_lambda_expression.cpp
 2 // compile with: /W4 /EHsc
 3 #include <iostream>
 4 using namespace std;
 5
 6 int main()
 7 {
 8    int m = 0;
 9    int n = 0;
10    [&, n] (int a) mutable { m = ++n + a; }(4);
11    cout << m << endl << n << endl;
12 }

Output:

5
0
更多详情请看 https://msdn.microsoft.com/en-us/library/dd293603.aspx
时间: 2024-10-24 12:20:33

C++学习:lambda表达式入门的相关文章

Java Lambda表达式入门[转]

原文链接: Start Using Java Lambda Expressions http://blog.csdn.net/renfufei/article/details/24600507 下载示例程序 Examples.zip .原文日期: 2014年4月16日 翻译日期: 2014年4月27日翻译人员: 铁锚简介(译者注:虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能.本人建议不要

Java Lambda表达式入门

原文链接: Start Using Java Lambda Expressions 下载示例程序 Examples.zip . 原文日期: 2014年4月26日 翻译日期: 2014年4月27日 翻译人员: 铁锚 简介 (译者注:虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能.本人建议不要乱用,因为这就和某些很高级的黑客写的代码一样,简洁,难懂,难以调试,维护人员想骂娘.) Lambda表

Java8 Lambda表达式入门

Lambda表达式的实质就是一个匿名函数.C#3.0引入了Lambda表达式,Java8也不甘示弱.Java8发布很久了,今天安装了JDK体验了Java8中的Lambda表达式. 首先看一个不适用Lambda表达式的例子. 比如我们要对一组字符串进行排序. public class Hello { public static void main(String[] args) { List<String> names = Arrays.asList("Tan", "

Lambda表达式入门

Lambda表达式是Java 8的重要更新,也是一个被广大开发者期待已久的新特性,Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例. Lambda表达式的主要作用就是代替匿名内部类的烦琐语法,它由三部分组成: 1.形参列表(参数),形参列表允许省略形参类型.如果形参列表中只有一个参数.甚至连形参列表的圆括号也可以省略: 2.箭头(->),必须通过英文中划线号和大于号组成: 3.代码块,如果代码块中只有

java8之lambda表达式入门

1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ private String name; private Double score; public Student(String name, Double score) { this.name = name; this.score = score; } public String getName() { ret

Python学习-lambda表达式

lambda只是一个表达式,函数体比def简单很多.lambda的主体是一个表达式,而不是一个代码块.仅仅能在lambda表达式中封装有限的逻辑进去.lambda表达式是起到一个函数速写的作用.允许在代码内嵌入一个函数的定义. #求三个数的和1 f = lambda x,y,z:x+y+x 2 print(f(1,2,3)) #4 3 4 f = lambda x,y,z:x+y+z 5 print(f(1,2,3)) #6 在常规的def函数构造中,可以有任意数量的语句,并且在def函数定义中

9.Lambda表达式入门

一.lambda表达式的优点: 1. 不需要指出重写的方法名字 2.不需要给出重写方法的返回值类型--只需要给出重写的方法括号及括号里的形参表即可 3.当使用lambda表达式代替匿名内部类创建对象时,lambda表达式的代码块将会代替实现抽象方法的方法体,lambda表达式就相当于一个匿名方法 介绍使用:                   1.lambda表达式的代码值包含一条语句,lambda表达式允许省略代码块的花括号                      2.形参列表中只有一个参数

JAVA 8 主要新特性 ----------------(三)新功能Lambda表达式入门

一.简述 Java为了扩充匿名方法在1.8中新追加的特性.本身Java之前的版本是没有匿名方法的,只有匿名对象. 二.使用 Java中使用匿名方法必须要对应接口中的一个抽象方法.(要有一个匿名方法,需要函数去接收它) 三.为什么使用 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升. 四.实例一:从匿名类到 Lamb

C#学习日记25---匿名方法 与 Func委托 与 lambda表达式

       在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法.C# 2.0 引入了匿名方法(委托),而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式. 匿名委托(方法): 匿名委托的叫法并不准确,准确的应该叫做匿名方法,(总之两者是一个意思啦).前面  委托类型  中我已经提到过,委托是用于引用与其具有相同标签的方法.换句话说,您可以使用委托对象调用可由委托引用的方法(参数是方法名).而匿名方法则是将代码块作为委托参数(参数是实