红颜莎娜
问题C ++包含有用的通用函数,例如std::for_each和std::transform,它们非常方便。不幸的是,他们也可以是相当繁琐的使用,特别是如果函子,你想申请是唯一的特定功能。#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一次并且在那个特定的地方,那么写一个全班只是为了做一些微不足道的事情似乎有点过分了。在C ++ 03中,您可能想要编写类似下面的内容,以保持函数本地:void func2(std::vector<int>& v) {
struct {
void operator()(int) {
// do something
}
} f;
std::for_each(v.begin(), v.end(), f);}但是这是不允许的,f不能传递给C ++ 03中的模板函数。新的解决方案C ++ 11引入了lambdas,允许你编写一个内联的匿名函子来替换struct f。对于小的简单示例,这可以更清晰地阅读(它将所有内容保存在一个地方)并且可能更简单地维护,例如以最简单的形式:void func3(std::vector<int>& v) {
std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });}Lambda函数只是匿名函子的语法糖。返回类型在简单的情况下,lambda的返回类型是为您推导出来的,例如:void func4(std::vector<double>& v) {
std::transform(v.begin(), v.end(), v.begin(),
[](double d) { return d < 0.00001 ? 0 : d; }
);}但是当你开始编写更复杂的lambda时,很快就会遇到编译器无法推断出返回类型的情况,例如: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: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子句([]表达式),这些子句在这些示例中尚未使用,例如: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;
}
});}您可以通过引用和值捕获,您可以分别使用&和指定=:[&epsilon] 通过引用捕获[&] 通过引用捕获lambda中使用的所有变量[=] 按值捕获lambda中使用的所有变量[&, epsilon] 捕获变量,如[&],但epsilon值[=, &epsilon] 捕获变量,如[=],但epsilon通过引用默认情况下生成的operator()是const隐式,默认情况下,const当您访问它们时捕获将是。这具有以下效果:具有相同输入的每个调用将产生相同的结果,但是您可以将lambda标记为mutable请求operator()生成的不是const。