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

查看:109
本文介绍了什么是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_each std :: transform ,这可以非常方便。不幸的是,他们也可能很麻烦使用,特别是如果函子你想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中,你可能会写下类似的东西,以保持functor局部:

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介绍lambdas允许你写一个内联的匿名函数来替换 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; }
                 );
}

然而,当你开始写更复杂的lambdas时,返回类型不能由编译器推导,例如:

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] 指定默认捕获方式是通过引用和我们要捕获的

  • [=,& epsilon] 默认情况下按值捕获,但 epsilon 使用引用

  • [&epsilon] capture by reference
  • [&, epsilon] specify that the default way of capturing is by reference and what we want to capture
  • [=, &epsilon] capture by value by default, but for epsilon use reference instead

默认情况下, operator() const ,意味着捕获将是 const 默认情况下访问它们。这样做的效果是,使用相同输入的每个调用都会产生相同的结果,但您可以 mutable 标记为请求运算符()不是 const

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天全站免登陆