在Lambda表达式的上下文中,“capture”一词是什么意思?

23

能否有人提供一些关于此的见解?Lambda是否捕获外部变量,或者是外部环境捕获Lambda生成的值?某个变量被捕获是什么意思?


我不明白你所说的“或者外部世界是否捕获了由lambda产生的值”,但也许这个链接可以回答你的问题。 - Praetorian
它字面上意味着将对象(或对象的引用)复制到函数的范围内。该函数从创建它的环境中字面上“捕获”了一部分。这为其提供了上下文数据以进行操作。 - Galik
3个回答

23

这个 lambda 表达式正在捕获一个外部变量。

lambda 表达式是创建类的一种语法。捕获变量意味着该变量被传递给该类的构造函数。

lambda 表达式可以指定是按引用还是按值传递。例如:

[&] { x += 1; }       // capture by reference
[=] { return x + 1; } // capture by value

第一个产生的类大致如下:

class foo { 
    int &x;
public:
    foo(int &x) : x(x) {}
    void operator()() const { x += 1; }
};

第二个产生的类大致如下:

class bar {
    int x;
public:
    bar(int x) : x(x) {}
    int operator()() const { return x + 1; }
};

就像大多数引用的使用一样,通过引用捕获可能会创建一个悬空引用,如果闭包(由lambda表达式创建的类对象)超出了被捕获的对象的生存期。


1
"Lambda是一种用于创建类的语法。" 不一定。 - RamblingMad
@CoffeeandCode:哦?还有其他选择吗? - Jerry Coffin
3
[](){/* ... body ... */}可以转换为一个普通函数指针void(*)(),因此可以作为一个独立的函数实现。无论如何,编译器可以通过各种技巧来捕获lambda函数。它可以定义接受指向局部变量的指针并对其进行解引用以进行捕获的函数。在某些情况下,它可以简单地将int x = /* captured value */附加到lambda函数体中。除了使用带有operator()()的类之外,还有许多实现方式。这完全取决于实现方式。 - RamblingMad
7
@CoffeeandCode: 嗯...标准好像与此不同 (§5.1.2/3):"lambda表达式的类型(也是闭包对象的类型)是一种唯一的、匿名的非联合类类型,称为闭包类型,其属性如下所述。" 当然,通常的“仿佛”规则适用于该类的实现,但这并不会使它变得不像一个类。 - Jerry Coffin
4
@CoffeeandCode,是的,这是一个带有转换运算符到函数指针的类。 - M.M

8

Jerry Coffin给你提供了详细的回答,我同意lambda是创建类的语法。有很多关于变量捕获和处理方式的选项。以下是选项列表:

[]  Capture nothing (or, a scorched earth strategy?)
[&] Capture any referenced variable by reference
[=] Capture any referenced variable by making a copy
[=, &foo]   Capture any referenced variable by making a copy, but capture variable foo by reference
[bar]   Capture bar by making a copy; don't copy anything else
[this]  Capture the this pointer of the enclosing class

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接