简体   繁体   English

C ++ 11 lambda捕获实际捕获了多少?

[英]How much does a C++11 lambda capture actually capture?

I've seen in multiple examples that you can use a single character to capture multiple variables like the following: 我在多个示例中看到,您可以使用单个字符捕获多个变量,如下所示:

Rect rect;
Point point;

auto someLambda = [&](const SomeType& var)
{
    if (rect.Contains(point))
    {
        var.Something();
    }

    this->MemberFunction();
};

This ends up grabbing rect and point by reference and also gives you access to this , but how much does it actually capture? 这最终抓住rectpoint参考,并且还让你访问this ,但多少它实际上捕捉? Does it only capture the variables that it needs, or does it capture literally everything there is in the current scope? 它只捕获它需要的变量,还是从字面上捕获当前范围内的所有变量?

I've seen in other examples that you can also specify individual variables to capture like this: 我在其他示例中看到,您还可以指定要捕获的各个变量:

Rect rect;
Point point;

auto someLambda = [this, &rect, &point](const SomeType& var)
{
    if (rect.Contains(point))
    {
        var.Something();
    }

    this->MemberFunction();
};

Is there any advantage to doing it one way or the other? 这样或那样做有什么好处吗? Someone I worked with once mentioned that using the "capture all" [&] version was more expensive but I can't find any documentation to back that up. 我曾与之合作的人曾提到使用“全部捕获” [&]版本更昂贵,但我找不到任何文档来支持这一点。 I just want to know for sure so I'm not making code more complex than it needs to be or doing expensive things that I shouldn't be doing. 我只想确切地知道,所以我不会让代码变得比它需要的更复杂或做一些我不应该做的昂贵的事情。

According to http://en.cppreference.com/w/cpp/language/lambda , the capture list (the part in the square braces) is: 根据http://en.cppreference.com/w/cpp/language/lambda ,捕获列表(方括号中的部分)是:

a comma-separated list of zero or more captures, optionally beginning with a capture-default. 以逗号分隔的零个或多个捕获列表,可选择以捕获默认值开头。 Capture list can be passed as follows [...]: 捕获列表可以如下传递[...]:

[a,&b] where a is captured by value and b is captured by reference. [a,&b]其中a按值捕获,b通过引用捕获。

[this] captures the this pointer by value [this]按值捕获this指针

[&] captures all automatic variables odr-used in the body of the lambda by reference [&]通过引用捕获lambda体中使用的所有自动变量

[=] captures all automatic variables odr-used in the body of the lambda by value [=]按值捕获lambda正文中使用的所有自动变量

[] captures nothing []什么也没捕捉到

This means that only the automatic (scope-lifetime) variables used in the body of the lambda will be captured. 这意味着只捕获lambda体中使用的自动(范围 - 生命周期)变量。

I can't see why capturing everything with [&] would be more expensive than individual captures, but one advantage of listing out the captures explicitly is that there's no chance of capturing something you didn't expect. 我不明白为什么用[&]捕获所有东西比单个捕获更昂贵,但明确列出捕获的一个优点是没有机会捕获你没想到的东西。

On the other hand, capturing with [=] could prove expensive since it will make copies of everything. 另一方面,用[=]捕获可能会证明是昂贵的,因为它会复制一切。 Perhaps that's what your coworker was referring to. 也许这就是你的同事所指的。

This ends up grabbing rect and point by reference and also gives you access to this, but how much does it actually capture? 这最终会抓住rect并逐个引用,并且还允许您访问它,但它实际捕获了多少?

When you capture with [&] it captures all the variables in the body of the lambda that have automatic storage duration and are odr-used. 使用[&]捕获时,它会捕获lambda正文中具有自动存储持续时间且使用频率的所有变量。

Here is an example: 这是一个例子:

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
}

If you know that you will only capture one variable, you don't need to capture everything by value / reference. 如果您知道只捕获一个变量,则不需要按值/引用捕获所有内容。

But on the other hand, if you know that you will be capturing a few variables, capturing them with [&] or [=] is easier than typing them all out. 但另一方面,如果你知道你将捕获一些变量,用[&][=]捕获它们比输入它们更容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM