C++ 中的Lambda表达式写法

2020-01-06 16:37:34王冬梅

n! = n * (n – 1) * (n – 2) * …

n!! = n * (n – 2) * (n – 4) * …

n!!! = n * (n – 3) * (n – 6) * …

要求编写3个函数,分别完成上述3种计算。

使用一般的方式写很容易实现,我们这里直接使用lambda表达式来实现:


#include <iostream>
#include <functional>
std::function<int(int)> getFactorialFunc(int n) {
 return [n](int x) {
  int fact = 1;
  for (; x >= 1; x -= n) fact *= x;
  return fact;
 };
}
int main() {
 // 构造要求的三个函数
 autofactorial1 = getFactorialFunc(1);
 autofactorial2 = getFactorialFunc(2);
 autofactorial3 = getFactorialFunc(3);
 // 调用
 std::cout << factorial1(10) << std::endl;
 std::cout << factorial2(10) << std::endl;
 std::cout << factorial3(10) << std::endl;
}

编译的时候要注意,lambda表达式是C++11开始支持的,所以需要指定一下C++的版本。


g++ factorial_lambda.cpp -o factorial_lambda.out --std=c++11

运行之后的结果为:

./factorial_lambda.out
3628800
3840
280

这里作为返回值的lambda表达式,可以访问先前传入的参数,这也就是闭包。具体的语法,我们后面会讲到。

3、柯里化(Currying)。这部分小喵也是第一次接触,维基百科有如下解释:

在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。 [3]

下面给出一个例子(也是实现之前的阶乘):


#include <iostream>
#include <functional>
// 两个参数的阶乘
int factorial(int n, int step) {
 int r = 1;
 for (; n >= 1; n -= step) {
  r *= n;
 }
 return r;
}
// curring化的阶乘
std::function<int(int)> currying_factorial(int step) {
 return [step](int n) {
  return factorial(n, step);
 };
}
int main() {
 // 调用普通函数
 std::cout << factorial(10, 1) << std::endl;
 std::cout << factorial(10, 2) << std::endl;
 std::cout << factorial(10, 3) << std::endl;
 // 调用currying函数
 std::cout << currying_factorial(1)(10) << std::endl;
 std::cout << currying_factorial(2)(10) << std::endl;
 std::cout << currying_factorial(3)(10) << std::endl;
 return 0;
}

4、lambda表达式整体可以被当做函数的参数或者返回值。

闭包和currying的例子就是将整个lambda表达式作为返回值。现在再举一个作为参数的例子:


#include <iostream>
#include <functional>
int operate(int x, int y, const std::function<int(int, int)> &op) {
 return op(x, y);
}
int main() {
 autoadd = [](int x, int y) { return x + y;};
 automul = [](int x, int y) { return x - y;};
 
 std::cout << operate(10, 5, add) << std::endl;
 std::cout << operate(10, 5, mul) << std::endl;
 return 0;
}