Rez*_*Rez 13 c++ lambda parameter-list
我正在学习 C++ 中的 Lambda 表达式,尽管我不是 C/C++ 的新手。我很难看到使用捕获子句与传入参数列表的老式参数将变量绘制到 Lambda 主体中进行操作的相对优点。我熟悉它们的语法差异以及每个中允许和不允许的内容,但只是不知道其中一个比另一个更有效?
如果您有内幕知识,或者对 Lambda 正在发生的事情有更好的了解,请告诉我。
非常感谢,雷扎。
考虑到 lambda 基本上只是函子的语法糖。例如
int x = 1;
auto f = [x](int y){ return x+y; };
Run Code Online (Sandbox Code Playgroud)
或多或少相当于
struct add_x {
int x;
add_x(int x) : x(x) {}
int operator()(int y) const { return x+y; }
}
int x = 1;
add_x f{x};
Run Code Online (Sandbox Code Playgroud)
当你传递 lambda 时,差异就会变得明显,例如
template <typename F>
void foo(F f) {
for (int i=0;i<10;++i) std::cout << f(i) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
类似的函数是使用 lambda 的主要动机之一,并且该函数(在本例中仅隐式地)指定了预期的签名。您可以foo致电
foo(f);
Run Code Online (Sandbox Code Playgroud)
但是如果你的仿函数 / lambda 也将作为x参数,那么你将无法将它传递给foo.
TL;DR:捕获的变量构成 lambda 的状态,而参数就像普通函数参数一样。
区别在于相同的捕获可以与不同的参数一起使用。
考虑下面的简单例子
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const int N = 10;
for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';
std::transform( std::begin( a ), std::end( a ), std::begin( a ),
[=]( const auto &item ) { return N * item; } );
for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
程序输出是
0 1 2 3 4 5 6 7 8 9
0 10 20 30 40 50 60 70 80 90
Run Code Online (Sandbox Code Playgroud)
lambda 的参数由算法 std::transform 提供。该算法无法将乘数 N 传递给 lambda。因此您需要捕获它,并且乘数将与传递给 lambda 的任何参数一起使用。