如果 capture 子句包含 capture-default & ,则该 capture 子句的 identifier 中没有任何 capture 可采用 & identifier 形式。 同样,如果 capture 子句包含 capture-default = ,则该 capture 子句的 capture 不能采用 = identifier 形式。 identifier 或 this 在 capture 子句中出现的次数不能超过一次。 以下代码片段给出了一些示例。
struct S { void f(int i); };
void S::f(int i) {
[&, i]{}; // OK
[=, &i]{}; // OK
[&, &i]{}; // ERROR: i preceded by & when & is the default
[=, this]{}; // ERROR: this when = is the default
[i, i]{}; // ERROR: i repeated
}
capture 后跟省略号是包扩展,如以下可变参数模板 [4] 示例中所示:
template<class... Args>
void f(Args... args) {
auto x = [args...] { return g(args...); };
x();
}
要在类方法的正文中使用 lambda 表达式,需要将this指针传递给 Capture 子句,以提供对封闭类的方法和数据成员的访问权限。
这里大家可能觉得有点奇怪,将this指针传给Capture子句?
其实我们常使用的成员函数也是用类似的方法实现的。我们知道,使用成员函数需要有一个类实例,但是调用类函数就不需要。这是因为成员函数的第一个参数是this,当然这个参数我们编写代码的时候不需要自己手动写出,而是默认的。使用像python这样的语言的时候就是需要显示的写出的。在使用类实例调用成员函数的时候,会默认将this指针传入。成员函数有这么一个参数,就可以访问类实例的各种变量和方法。而类函数是没有这个参数的,也就是没有this这个指针,因此它的调用并不需要类实例,当然也就不能访问类实例的变量。
在使用 capture 子句时,要记住以下几点(尤其是使用采取多线程的 lambda 时):
引用捕获可用于修改外部变量,而值捕获却不能实现此操作。 (mutable允许修改副本,而不能修改原始项。)
引用捕获会反映外部变量的更新,而值捕获却不会反映。
引用捕获引入生存期依赖项,而值捕获却没有生存期依赖项。 当 lambda 以异步方式运行时,这一点尤其重要。 如果在异步 lambda 中通过引用捕获本地变量,该本地变量将很可能在 lambda 运行时消失,从而导致运行时访问冲突。
通用捕获 (C++14)
在 C++14 中,可在 Capture 子句中引入并初始化新的变量,而无需使这些变量存在于 lambda 函数的封闭范围内。 初始化可以任何任意表达式表示;且将从该表达式生成的类型推导新变量的类型。 此功能的一个好处是,在 C++14 中,可从周边范围捕获只移动的变量(例如 std::unique_ptr)并在 lambda 中使用它们。










