【问题标题】:Can a lambda capturing nothing access global variables?什么都不捕获的 lambda 可以访问全局变量吗?
【发布时间】:2021-11-12 17:15:11
【问题描述】:
int n;    
int main()
{
    [](){ n = 0; }(); // clang says "ok"

    int m;
    [](){ m = 0; }(); // clang says "not ok"
}

我只是想知道:

如果 lambda 没有捕获任何内容,是否允许按照 C++ 标准访问全局变量?

【问题讨论】:

  • 我会假设是这样,因为您可以在不捕获它们的情况下使用其他全局事物(函数和类型)。想象一下,如果您必须捕获 C++ 算法函数(例如 std::find)才能从 lambda 中使用它们。
  • en.cppreference.com/w/cpp/language/lambda 说了一些关于capture-default 的事情。我无法详细弄清楚它的作用。
  • 如果您考虑一下,lambda 只是使用函数运算符定义 struct 的捷径。局部变量不在struct 成员函数的范围内,但全局变量在。
  • 全局变量无法被捕获。
  • @cpplearner "无法捕获全局变量。"?有参考吗?

标签: c++ c++11 lambda global-variables standards


【解决方案1】:

是的,当然。正常的名称查找规则适用。

[expr.prim.lambda]/7 ... 用于名称查找 ... compound-statement 被考虑在 lambda 表达式

Re:为什么局部变量的处理方式与全局变量不同。

[expr.prim.lambda]/13 ... 如果 lambda-expression 或泛型 lambda odr-uses 的函数调用运算符模板的实例化(3.2) this 或从其到达范围内具有自动存储持续时间的变量,该实体应由 lambda-expression 捕获。

[expr.prim.lambda]/9 一个 lambda 表达式,其最小的封闭范围是一个块范围 (3.3.3) 是一个 本地 lambda表达式...局部 lambda 表达式的到达作用域是一组封闭作用域,直到并包括最里面的封闭函数及其参数。

在您的示例中,m 是一个变量,具有 lambda 到达范围的自动存储持续时间,因此应被捕获。 n 不是,所以也不一定是。

【讨论】:

  • 给定的引用说明与全局变量无关。
  • 如果n是本地的,则代码是非法的。如果n 是全局的,为什么它是合法的?
  • @xmllmx 添加了对局部变量为何表现不同的解释。
【解决方案2】:

实际上[](){ n = 10; }(); 并没有捕获任何东西,而是使用了全局变量。

int n;    
int main()
{
    [](){ n = 10; }(); // clang says "ok"
    std::cout << n; // output 10
}

capture-list in Explaination

capture-list - 零个或多个捕获的逗号分隔列表,可选择以 capture-default 开头。

捕获列表可以按如下方式传递(详见下文 描述):

  • [a,&b] 其中 a 通过副本捕获,b 通过引用捕获。
  • [this] 通过引用捕获当前对象(*this)
  • [&] 通过引用捕获 lambda 主体中使用的所有自动变量,如果存在则通过引用捕获当前对象
  • [=] 通过副本捕获 lambda 主体中使用的所有自动变量,并通过引用捕获当前对象(如果存在)
  • [ ] 没有捕获任何内容

【讨论】:

  • 当前对象的引用如果存在”?那是什么?你能详细解释一下吗?
【解决方案3】:

默认访问全局、​​静态和常量变量:

#include <iostream>

int n;    
int main()
{
    [](){ n = 10; }();
    std::cout << n << std::endl;
    static int m = 1;
    [](){ m = 100; }();
    std::cout << m << std::endl;
    const int l = 200;
    [](){ std::cout << l << std::endl; }();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    • 2019-07-31
    相关资源
    最近更新 更多