lambda表达式与仿函数

1. lambda表达式

C++ 11 中的 Lambda 表达式用于定义并创建匿名的函数对象,以简化编程工作。
Lambda 的语法形式如下:

[capture] (parameters) mutable 或 exception->return-type{statement}

可以看到,Lambda 主要分为五个部分:[捕捉列表]、(操作符重载函数参数)、mutable 或 exception 声明、-> 返回值类型、{函数体}。

语法分析

1.1 [捕捉列表]

捕捉列表总是出现在lambda函数的开始处。事实上,[]lambda引出符,编译器根据该引出符判断接下来的代码是否是lambda函数。捕捉列表能够捕捉上下文中的变量以供lambda使用,具体有以下形式:

  • []没有任何函数对象参数。
  • [=]函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
  • [&]函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式(相当于是编译器自动为我们按引用传递了所有局部变量)。
  • [this]函数体内可以使用 lambda 所在类中的成员变量。
  • [a] a 按值进行传递。按值进行传递时,函数体内不能修改传递进来的 a 的拷贝,因为默认情况下函数是 const 的,要修改传递进来的拷贝,可以添加 mutable 修饰符。
  • [&a] a 按引用进行传递。
  • [a, &b] a 按值传递,b 按引用进行传递。
  • [=, &a, &b] a b 按引用进行传递外,其他参数都按值进行传递。
  • [&, a, b]: a b 按值进行传递外,其他参数都按引用进行传递。

1.2 (操作符重载函数参数)

参数列表,与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号()一起省略。

1.3 mutable exception 声明

mutable修饰符,默认情况下, lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。

exception修饰符,声明用于指定函数抛出的异常,如抛出整数类型的异常,可以使用 throw(int)

1.4 ->返回值类型

用追踪返回类型形式声明函数的返回类型。处于方便,不需要返回值的时候可以连同符号->一起省略。此外,在返回值类型明确的情况下(只有一个return)也可以省略该部分,让编译器对返回类型进行推导。

1.5 {statement}

函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量,不可省略。

我们看一个lambda的例子:

 

2.lambda与仿函数

我们在使用STL算法时,通常会使用到一种特别的对象,我们称之为函数对象,或者仿函数(functor)。简单地说,就是重定义了成员函数operator()的一种自定义类型对象,其使用在代码层面感觉跟函数的使用并无二样,但究其本质却并非函数。我们看一个仿函数的例子

 

这个例子中,class_functor的operator()被重载,因此,在调用该函数的使用,我们看到跟函数调用一样的形式,只不过这里的totalChild不是函数名称,而是对象名称。

我们再看一个例子:

 

该例中,分别使用了仿函数和lambda两种方式来完成扣税后的产品价格计算。在这里我们看到,lambda函数捕捉了tax_rate变量,而仿函数则以tax_rate初始化类。其他的,如在参数传递上,两者保持一致。可以看到,除去在语法层面上的不同,lambda和仿函数却有着相同的内涵—都可以捕捉一些变量作为初始状态,并接受参数进行运算。

而事实上,仿函数是编译器实现lambda的一种方式。在现阶段,通常编译器都会把lambda转化为一个仿函数对象。我们可以通过下图直观的了解lambda和仿函数是如何等价的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值