lambda如何捕获局部静态变量?

时间:2017-04-02 14:56:29

标签: c++ c++11

在下面的代码中,我没有指定任何捕获模式,但some_static在闭包内可见。所以问题是它是否实际被捕获,或者以某种方式以其他方式引用。

额外的问题是,是否允许编译器将这样的lambda转换为自由函数而不是闭包 - 这是可能的,因为没有指定捕获列表。

std::vector<std::function<bool(int)>> filters;

int main()
{
    static int some_static = 1;
    filters.emplace_back([](int){
      return some_static == 2;
    });
}

2 个答案:

答案 0 :(得分:6)

您无需捕获全局变量或static变量。如果要使用它们,只需要捕获自动变量。

因此,是的,您可以将这样的lambda转换为函数指针。

Cppreference:

  

在lambda的到达范围内使用通常的非限定名称查找来查找没有初始化程序(除了this-capture)的任何捕获中的标识符。查找的结果必须是在到达范围内声明的具有自动存储持续时间的变量。

(强调我的)

“捕获”意味着将变量或引用放入lambda对象本身。

全局和static变量具有固定内存位置。您不需要存储副本或对它们的引用来使用它们,因为它们的位置在编译时是已知的并且不会更改。

(如果您真的想拥有全局或static变量的副本,可以使用C ++ 14中的 named capture 创建它,这样您就可以创建它lambda对象中的自定义成员变量。但如果您只想使用该全局/ static变量,则此类捕获不必。)

另一方面,自动变量没有固定位置。在完全相同的位置创建的多个lambda可以引用不同的自动变量。因此,lambda对象必须捕获这样的变量 - 这意味着包含对使用过的自动变量或其副本的引用。

答案 1 :(得分:1)

通常,lambda实现为具有变量和单个成员函数的类(在幕后)。但是当它捕获静态时,这是不必要的 - 因为代码是由编译器生成的,它没有范围规则,它可以直接访问静态。因此,仅捕获静态变量的lambda将具有空的类成员列表,并且可能优化为简单的函数指针。