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

时间:2016-05-09 22:21:37

标签: c++ performance c++11 lambda

我在多个示例中看到,您可以使用单个字符捕获多个变量,如下所示:

Rect rect;
Point point;

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

    this->MemberFunction();
};

最终通过引用获取rectpoint,并且您还可以访问this,但它实际捕获了多少?它只捕获它需要的变量,还是从字面上捕获当前范围内的所有变量?

我在其他示例中看到,您还可以指定要捕获的各个变量:

Rect rect;
Point point;

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

    this->MemberFunction();
};

以某种方式做到这一点有什么好处吗?我曾与之合作的人曾提到使用"捕捉所有" [&]版本更贵,但我无法找到任何支持该文档的文档。我只想确切地知道,所以我不会让代码变得比它需要的更复杂,或者做一些我不应该做的昂贵的事情。

2 个答案:

答案 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
}

如果您知道只捕获一个变量,则无需按值/参考捕获所有内容。

但另一方面,如果您知道自己将捕获一些变量,那么使用[&][=]捕获它们比将它们全部输入更容易。