C++ Lambda函数

brownfrog 发布于2月前 阅读662次
0 条评论
 

Lambda的概念起源于数学中的Lambda演算(也叫λ 演算),当然,我们今天要讨论的不是数学(我也不懂J),而是编程。Lambada在程序设计中指的是‘匿名函数’。 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。 我们今天就来看看C++ 11中引入的Lambda 表达式。

引子

为了直观,我们先看一个例子:C++的标准库中有一个常用算法的库,其中提供了很多算法函数,比如 sort()。我们先来看看sort的一般使用方法:

// sort algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::sort
#include <vector>       // std::vector

bool myfunction (int i,int j) { return (i<j); }

struct myclass {
  bool operator() (int i,int j) { return (i<j);}
} myobject;

int main () {
  int myints[] = {32,71,12,45,26,80,53,33};
  std::vector<int> myvector (myints, myints+8);               // 32 71 12 45 26 80 53 33

  // using default comparison (operator <):
  std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33

  // using function as comp
  std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)

  // using object as comp
  std::sort (myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80)

  // print out content:
  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}
 

可以看到在使用function comparison或者object comparison的时候,我们都需要提前先定义好comparison函数。 这其实是一个(污染环境的)函数,尤其如果这个函数只会使用一次的话。

而如果使用Lambda函数会怎么样呢?

// using Lambda函数
std::sort (myvector.begin(), myvector.end(), [](int i,int j) { return (i<j); });     //(12 26 32 33 45 53 71 80)
 

可以看到,这种写法实际上更易读,因为这个comparison函数具体是要做什么,非常一目了然。如果你仔细观察自己的代码,会发现这种场景其实很常见:你在某处就真的只需要一个能做一件事情的函数而已,连它叫什么名字都无关紧要。Lambda 表达式就可以用来做这件事。

利用 lambda 表达式创建那些“只用一次”或者比较短小的函数非常方便和高效。

语法

下面来看一下Lambda函数如何使用:

[ capture ] ( params ) mutable exception attribute -> ret { body }	(1)	
[ capture ] ( params ) -> ret { body }	(2)	
[ capture ] ( params ) { body }	(3)	
[ capture ] { body }	(4)
 

1) 完整的声明

2) 一个常lambda的声明:按副本捕获的对象不能被修改。

3) 省略后缀返回值类型:闭包的operator()的返回值类型是根据以下规则推导出的:

如果body仅包含单一的return语句,那么返回值类型是返回表达式的类型(在此隐式转换之后的类型:右值到左值、数组与指针、函数到指针)

否则,返回类型是void

4) 省略参数列表:函数没有参数,即参数列表是()

解释:

  • mutable - 允许body修改传值进来的形参,以及调用它们的非常成员函数。

  • exception - 提供闭包类型的operator()成员函数的异常说明或noexcept语句

  • attribute - 提供闭包类型的operator()成员函数的属性说明

  • capture - 指定哪些在函数声明处的作用域中可见的符号将在函数体内可见。

    符号表可按如下规则传入:

    • [] : 不捕获任何外部变量

    • [&] : 通过引用方式捕获所有外部变量

    • [=] : 通过拷贝方式捕获所有外部变量

    • [=, &foo] : 通过引用方式捕获 foo 变量,其他外部变量通过拷贝方式捕获

    • [bar] : 通过拷贝方式捕获 bar 变量

    • [this] : 捕获当前类的 this 指针

  • params - 参数列表,与命名函数一样

  • ret - 返回值类型。如果不存在,它由该函数的return语句来隐式决定(或者是void,例如当它不返回任何值的时候)

  • body - 函数体

Reference

共收到0条回复

需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。