C++ 在lambda函数语法中,';捕获列表';发球?
例如,这是一个代码,用于计算C++ 在lambda函数语法中,';捕获列表';发球?,c++,c++11,lambda,C++,C++11,Lambda,例如,这是一个代码,用于计算std::vector: std::for_each( vector.begin(), vector.end(), [&](int n) { sum_of_elems += n; } ); 我理解lambda函数只是无名函数 我理解lambda函数语法 我不明白为什么lambda函数需要捕获列表,而普通函数不需要 捕获列表提供了哪些额外信息 为什么正常功能不需要这些信息 lambda函数不仅仅是无名函数吗 从您
std::vector
:
std::for_each(
vector.begin(),
vector.end(),
[&](int n) {
sum_of_elems += n;
}
);
我理解lambda函数只是无名函数
我理解lambda函数语法
我不明白为什么lambda函数需要捕获列表,而普通函数不需要
从您给出的语法链接中,捕获列表“定义lambda外部的哪些内容应该在函数体中可用以及如何使用” 普通函数可以通过以下几种方式使用外部数据:
[=, &epsilon]
编辑:
区分签名和lambda内部使用的内容很重要。lambda的签名是参数类型的有序列表,加上返回值的类型
例如,一元函数接受特定类型的单个值,并返回另一类型的值
但是,在内部,它可以使用其他值。举个简单的例子:
[x, y](int z) -> int
{
return x + y - z;
}
lambda的调用者只知道它接受int
并返回int
。然而,在内部,它碰巧使用了另外两个变量的值
lambda函数不仅仅是无名函数吗
对!!除了匿名之外,它们还可以引用词汇范围内的变量。在您的例子中,一个例子是sum\u of_elems
变量(我想它既不是参数也不是全局变量)。C++中的正常函数不能实现。< /P>
捕获列表提供了哪些额外信息
捕获列表提供了
您可以使用capture default符号使编译器捕获所有需要的变量,该符号仅指定默认捕获模式(在您的示例中:
&
=>reference;=
将是value)。在这种情况下,基本上会捕获lambda中从外部作用域引用的所有变量。我们试图解决的基本问题是,某些算法要求函数只接受一组特定的参数(在您的示例中为一个int
)。但是,我们希望函数能够操纵或检查其他对象,可能如下所示:
void what_we_want(int n, std::set<int> const & conditions, int & total)
{
if (conditions.find(n) != conditions.end()) { total += n; }
}
现在我们可以用一个适当初始化的函子调用该算法:
std::set<int> conditions;
int total;
for_each(v.begin(), v.end(), what_we_must_write(conditions, total));
简写的捕获列表[=]
和[&]
只捕获“所有内容”(分别通过值或引用),这意味着编译器会为您计算出具体的捕获列表(它实际上不会将所有内容都放入closure对象中,而只将您需要的内容放入其中)
因此,简而言之:一个没有捕获的闭包对象就像一个自由函数,一个有捕获的闭包就像一个有适当定义和初始化的私有成员对象的函子对象。考虑一下:
std::function<int()>
make_generator(int const& i)
{
return [i] { return i; };
}
// could be used like so:
int i = 42;
auto g0 = make_generator(i);
i = 121;
auto g1 = make_generator(i);
i = 0;
assert( g0() == 42 );
assert( g1() == 121 );
std::函数
make_发生器(内部常数和i)
{
return[i]{return i;};
}
//可以这样使用:
int i=42;
auto g0=制造发电机(i);
i=121;
自动g1=制造发电机(i);
i=0;
断言(g0()==42);
断言(g1()==121);
请注意,在这种情况下,创建的两个生成器都有自己的i
。这是不能用普通函数重新创建的,因此这些函数不使用捕获列表。捕获列表解决一个版本的
lambda函数不仅仅是无名函数吗
这是一个非常聪明的问题。lambda表达式创建的对象实际上比常规函数更强大:它们是(并且标准确实将lambda表达式创建的对象称为“闭包对象”)。简单地说,闭包是一个结合了绑定范围的函数。C++语法选择了一种常见的函数形式的函数位(具有函数体的延迟返回类型的参数列表,部分是可选的),而捕获列表是指定哪个局部变量将参与绑定范围的语法(非局部变量被自动引入)。
注意,其他具有闭包的语言通常没有与C++捕获列表类似的构造。C++由于其内存模型(本地变量只活在本地范围内)而设计了捕获列表的选择,并且它的哲学不为不使用的东西付费(如果本地变量被捕获时自动地活得更长)可能不是理想的。
auto what_we_get = [&conditions, &total](int n) -> void {
if (condiditons.find(n) != conditions.end()) { total += n; } };
std::function<int()>
make_generator(int const& i)
{
return [i] { return i; };
}
// could be used like so:
int i = 42;
auto g0 = make_generator(i);
i = 121;
auto g1 = make_generator(i);
i = 0;
assert( g0() == 42 );
assert( g1() == 121 );