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

How much does a C++11 lambda capture actually capture?

本文关键字:多少 C++11 lambda      更新时间:2023-10-16

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

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();
};

这样或那样做有什么好处吗?我的同事曾经提到,使用"捕获所有"[&]版本更贵,但我找不到任何文档来支持这一点。我只是想确定一下,这样我就不会让代码变得比它需要的更复杂,也不会做我不应该做的昂贵的事情。

根据http://en.cppreference.com/w/cpp/language/lambda,捕获列表(方括号中的部分)为:

以逗号分隔的零个或多个捕获的列表,可选地以开头具有捕获默认值。捕获列表可以按如下方式传递[…]:

[a,&b]其中a是通过值捕获的,b是通过引用捕获的。

[this]通过值捕获该指针

[&]捕获的正文中使用的所有自动变量odrλ参考

[=]捕获所有使用的自动变量odr在lambda的主体中按值

[]未捕获任何

这意味着只有lambda主体中使用的自动(作用域生存期)变量才会被捕获。

我不明白为什么用[&]捕获所有内容会比单个捕获更昂贵,但明确列出捕获的一个好处是,没有机会捕获到你意想不到的东西。

另一方面,使用[=]进行捕获可能代价高昂,因为它可以复制所有内容。也许这就是你的同事所指的。

这最终通过引用获取rect和point,也让您可以访问它,但它实际捕获了多少?

当您使用[&]捕获时,它会捕获lambda主体中具有自动存储持续时间并使用odr的所有变量。

这里有一个例子:

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
}

如果您知道只捕获一个变量,则不需要按值/引用捕获所有变量。

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