什么是 C++11 中的 lambda 表达式?我什么时候用一个?他们解决了哪类问题在引入之前是不可能的?
几个例子和用例会很有用。
原文由 Nawaz 发布,翻译遵循 CC BY-SA 4.0 许可协议
C++ 11 引入了 lambda 表达式以允许我们编写一个内联函数,该函数可用于短代码片段
[ capture clause ] (parameters) -> return-type
{
definition of method
}
通常 lambda 表达式中的 return-type 由编译器本身评估,我们不需要显式指定和 -> return-type 部分可以忽略,但在一些复杂的情况下,如条件语句,编译器无法确定返回类型,我们需要指定。
// C++ program to demonstrate lambda expression in C++
#include <bits/stdc++.h>
using namespace std;
// Function to print vector
void printVector(vector<int> v)
{
// lambda expression to print vector
for_each(v.begin(), v.end(), [](int i)
{
std::cout << i << " ";
});
cout << endl;
}
int main()
{
vector<int> v {4, 1, 3, 5, 2, 3, 1, 7};
printVector(v);
// below snippet find first number greater than 4
// find_if searches for an element for which
// function(third argument) returns true
vector<int>:: iterator p = find_if(v.begin(), v.end(), [](int i)
{
return i > 4;
});
cout << "First number greater than 4 is : " << *p << endl;
// function to sort vector, lambda expression is for sorting in
// non-decreasing order Compiler can make out return type as
// bool, but shown here just for explanation
sort(v.begin(), v.end(), [](const int& a, const int& b) -> bool
{
return a > b;
});
printVector(v);
// function to count numbers greater than or equal to 5
int count_5 = count_if(v.begin(), v.end(), [](int a)
{
return (a >= 5);
});
cout << "The number of elements greater than or equal to 5 is : "
<< count_5 << endl;
// function for removing duplicate element (after sorting all
// duplicate comes together)
p = unique(v.begin(), v.end(), [](int a, int b)
{
return a == b;
});
// resizing vector to make size equal to total different number
v.resize(distance(v.begin(), p));
printVector(v);
// accumulate function accumulate the container on the basis of
// function provided as third argument
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int f = accumulate(arr, arr + 10, 1, [](int i, int j)
{
return i * j;
});
cout << "Factorial of 10 is : " << f << endl;
// We can also access function by storing this into variable
auto square = [](int i)
{
return i * i;
};
cout << "Square of 5 is : " << square(5) << endl;
}
输出
4 1 3 5 2 3 1 7
First number greater than 4 is : 5
7 5 4 3 3 2 1 1
The number of elements greater than or equal to 5 is : 2
7 5 4 3 2 1
Factorial of 10 is : 3628800
Square of 5 is : 25
通过从封闭范围访问变量,lambda 表达式可以比普通函数更强大。我们可以通过三种方式从封闭范围中捕获外部变量:
用于捕获变量的语法:
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> v1 = {3, 1, 7, 9};
vector<int> v2 = {10, 2, 7, 16, 9};
// access v1 and v2 by reference
auto pushinto = [&] (int m)
{
v1.push_back(m);
v2.push_back(m);
};
// it pushes 20 in both v1 and v2
pushinto(20);
// access v1 by copy
[v1]()
{
for (auto p = v1.begin(); p != v1.end(); p++)
{
cout << *p << " ";
}
};
int N = 5;
// below snippet find first number greater than N
// [N] denotes, can access only N by value
vector<int>:: iterator p = find_if(v1.begin(), v1.end(), [N](int i)
{
return i > N;
});
cout << "First number greater than 5 is : " << *p << endl;
// function to count numbers greater than or equal to N
// [=] denotes, can access all variable
int count_N = count_if(v1.begin(), v1.end(), [=](int a)
{
return (a >= N);
});
cout << "The number of elements greater than or equal to 5 is : "
<< count_N << endl;
}
输出:
First number greater than 5 is : 7
The number of elements greater than or equal to 5 is : 3
原文由 sun1211 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
问题
C++ 包含有用的通用函数,例如
std::for_each
和std::transform
,非常方便。不幸的是,它们使用起来也很麻烦,特别是如果您要应用的 函子 对于特定函数是唯一的。如果你只使用
f
一次并且在那个特定的地方,编写一个完整的课程只是为了做一些微不足道的事情似乎有点过头了。在 C++03 中,您可能很想编写类似以下内容,以保持函子本地化:
但是这是不允许的,
f
不能传递给 C++03 中的 模板 函数。新的解决方案
C++11 引入了 lambda,允许您编写一个内联的匿名仿函数来替换
struct f
。对于小的简单示例,这可以更清晰地阅读(它将所有内容保存在一个地方)并且可能更易于维护,例如以最简单的形式:Lambda 函数只是匿名函子的语法糖。
返回类型
在简单的情况下,会为您推导出 lambda 的返回类型,例如:
但是,当您开始编写更复杂的 lambda 表达式时,您将很快遇到编译器无法推断返回类型的情况,例如:
要解决此问题,您可以使用
-> T
显式指定 lambda 函数的返回类型:“捕获”变量
到目前为止,除了传递给其中的 lambda 之外,我们没有使用任何其他变量,但我们也可以在 lambda 中使用其他变量。如果您想访问其他变量,您可以使用捕获子句(表达式的
[]
),迄今为止在这些示例中未使用该子句,例如:您可以通过引用和值来捕获,您可以分别使用
&
和=
指定:[&epsilon, zeta]
通过引用捕获 epsilon,按值捕获 zeta[&]
通过引用捕获lambda中使用的所有变量[=]
按值捕获 lambda 中使用的所有变量[&, epsilon]
通过引用捕获 lambda 中使用的所有变量,但按值捕获 epsilon[=, &epsilon]
通过值捕获 lambda 中使用的所有变量,但通过引用捕获 epsilon生成的
operator()
默认为const
,默认情况下捕获的将是const
。这具有相同输入的每次调用都会产生相同结果的效果,但是您可以 将 lambda 标记为mutable
以请求产生的operator()
不是const
。