我在多个示例中看到,您可以使用单个字符捕获多个变量,如下所示:
Rect rect;
Point point;
auto someLambda = [&](const SomeType& var)
{
if (rect.Contains(point))
{
var.Something();
}
this->MemberFunction();
};
最终通过引用获取rect
和point
,并且您还可以访问this
,但它实际捕获了多少?它只捕获它需要的变量,还是从字面上捕获当前范围内的所有变量?
我在其他示例中看到,您还可以指定要捕获的各个变量:
Rect rect;
Point point;
auto someLambda = [this, &rect, &point](const SomeType& var)
{
if (rect.Contains(point))
{
var.Something();
}
this->MemberFunction();
};
以某种方式做到这一点有什么好处吗?我曾与之合作的人曾提到使用"捕捉所有" [&]
版本更贵,但我无法找到任何支持该文档的文档。我只想确切地知道,所以我不会让代码变得比它需要的更复杂,或者做一些我不应该做的昂贵的事情。
答案 0 :(得分:7)
根据http://en.cppreference.com/w/cpp/language/lambda,捕获列表(方括号中的部分)是:
以逗号分隔的零个或多个捕获列表,可选择从头开始 使用捕获默认值。捕获列表可以按如下方式传递[...]:
[a,& b]其中a由值捕获,b通过引用捕获。
[this]按值
捕获this指针[&]捕获在体内使用的所有自动变量 lambda by reference
[=]捕获odr使用的所有自动变量 在lambda的体内按值
[]没有捕获任何内容
这意味着只会捕获lambda正文中使用的自动(范围 - 生命周期)变量。
我无法理解为什么使用[&]
捕获所有内容会比单个捕获更加昂贵,但明确列出捕获的一个优点是没有机会捕获您没想到的内容。
另一方面,使用[=]
进行捕获可能会很昂贵,因为它会复制一切。也许这就是你的同事所指的。
答案 1 :(得分:1)
这最终会抓住rect并逐个引用,并且还允许您访问它,但它实际捕获了多少?
当您使用[&]
进行捕获时,它会捕获lambda正文中具有自动存储持续时间并且使用率较高的所有变量。
以下是一个例子:
int main()
{
int num = 50;
[&] { std::cout << num << '\n'; }(); // num captured by reference
[=] { std::cout << num << '\n'; }(); // num captured by value
[&num] { std::cout << num << '\n'; }(); // by reference
[num] { std::cout << num << '\n'; }(); // by value
}
如果您知道只捕获一个变量,则无需按值/参考捕获所有内容。
但另一方面,如果您知道自己将捕获一些变量,那么使用[&]
或[=]
捕获它们比将它们全部输入更容易。