什么是 C++11 中的 lambda 表达式? [英] What is a lambda expression in C++11?

查看:37
本文介绍了什么是 C++11 中的 lambda 表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是 C++11 中的 lambda 表达式?我什么时候用一个?他们解决了哪些问题在引入之前是不可能的?

What is a lambda expression in C++11? When would I use one? What class of problem do they solve that wasn't possible prior to their introduction?

一些示例和用例会很有用.

A few examples, and use cases would be useful.

推荐答案

问题

C++ 包含有用的通用函数,例如 std::for_eachstd::transform,它们非常方便.不幸的是,它们使用起来也很麻烦,特别是如果 functor 你想要apply 是特定函数所独有的.

The problem

C++ includes useful generic functions like std::for_each and std::transform, which can be very handy. Unfortunately they can also be quite cumbersome to use, particularly if the functor you would like to apply is unique to the particular function.

#include <algorithm>
#include <vector>

namespace {
  struct f {
    void operator()(int) {
      // do something
    }
  };
}

void func(std::vector<int>& v) {
  f f;
  std::for_each(v.begin(), v.end(), f);
}

如果你只在那个特定的地方使用 f 一次,那么编写一整个类只是为了做一些微不足道的事情似乎有点过分.

If you only use f once and in that specific place it seems overkill to be writing a whole class just to do something trivial and one off.

在 C++03 中,您可能会想编写如下代码,以保持函子本地化:

In C++03 you might be tempted to write something like the following, to keep the functor local:

void func2(std::vector<int>& v) {
  struct {
    void operator()(int) {
       // do something
    }
  } f;
  std::for_each(v.begin(), v.end(), f);
}

但是这是不允许的,f 不能传递给 模板 C++03 中的函数.

however this is not allowed, f cannot be passed to a template function in C++03.

C++11 引入了 lambda 表达式,允许您编写一个内联的匿名函子来替换 struct f.对于小的简单示例,这可以更清晰地阅读(它将所有内容都放在一个地方)并且可能更易于维护,例如以最简单的形式:

C++11 introduces lambdas allow you to write an inline, anonymous functor to replace the struct f. For small simple examples this can be cleaner to read (it keeps everything in one place) and potentially simpler to maintain, for example in the simplest form:

void func3(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}

Lambda 函数只是匿名函子的语法糖.

Lambda functions are just syntactic sugar for anonymous functors.

在简单的情况下,会为您推导出 lambda 的返回类型,例如:

In simple cases the return type of the lambda is deduced for you, e.g.:

void func4(std::vector<double>& v) {
  std::transform(v.begin(), v.end(), v.begin(),
                 [](double d) { return d < 0.00001 ? 0 : d; }
                 );
}

但是,当您开始编写更复杂的 lambda 表达式时,您很快就会遇到编译器无法推断出返回类型的情况,例如:

however when you start to write more complex lambdas you will quickly encounter cases where the return type cannot be deduced by the compiler, e.g.:

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

要解决此问题,您可以使用 -> 显式指定 lambda 函数的返回类型.T:

To resolve this you are allowed to explicitly specify a return type for a lambda function, using -> T:

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) -> double {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

捕获"变量

到目前为止,除了传递给其中的 lambda 之外,我们还没有使用任何其他东西,但我们也可以在 lambda 中使用其他变量.如果您想访问其他变量,您可以使用 capture 子句(表达式的 []),到目前为止,这些示例中尚未使用该子句,例如:

"Capturing" variables

So far we've not used anything other than what was passed to the lambda within it, but we can also use other variables, within the lambda. If you want to access other variables you can use the capture clause (the [] of the expression), which has so far been unused in these examples, e.g.:

void func5(std::vector<double>& v, const double& epsilon) {
    std::transform(v.begin(), v.end(), v.begin(),
        [epsilon](double d) -> double {
            if (d < epsilon) {
                return 0;
            } else {
                return d;
            }
        });
}

您可以通过引用和值来捕获,您可以分别使用 &= 指定:

You can capture by both reference and value, which you can specify using & and = respectively:

  • [&epsilon, zeta] 按引用捕获 epsilon,按值捕获 zeta
  • [&] 通过引用捕获 lambda 中使用的所有变量
  • [=] 按值捕获 lambda 中使用的所有变量
  • [&, epsilon] 通过引用捕获 lambda 中使用的所有变量,但通过值捕获 epsilon
  • [=, &epsilon] 按值捕获 lambda 中使用的所有变量,但按引用捕获 epsilon
  • [&epsilon, zeta] captures epsilon by reference and zeta by value
  • [&] captures all variables used in the lambda by reference
  • [=] captures all variables used in the lambda by value
  • [&, epsilon] captures all variables used in the lambda by reference but captures epsilon by value
  • [=, &epsilon] captures all variables used in the lambda by value but captures epsilon by reference

生成的operator()默认是const,默认情况下,当你访问它们时,捕获的含义是const.这会导致具有相同输入的每次调用都会产生相同的结果,但是您可以 将 lambda 标记为 mutable 以请求生成的 operator() 不是 <代码>常量.

The generated operator() is const by default, with the implication that captures will be const when you access them by default. This has the effect that each call with the same input would produce the same result, however you can mark the lambda as mutable to request that the operator() that is produced is not const.

这篇关于什么是 C++11 中的 lambda 表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆