c++ - GCC 在 lambda 函数中通过引用错误地捕获全局变量?

标签 c++ gcc lambda c++11

GCC 似乎在 lambda 函数中通过引用错误地捕获全局变量,即使它们被指定为“按值捕获”。此代码将编译并打印“a = 9”:

#include <iostream>

int a = 10;

int main()
{
    [=]() { a = 9; } ();
    std::cout << "a = " << a << std::endl;
    return 0;
}

虽然这段代码不会编译:

#include <iostream>

int main()
{
    int a = 10;
    [=]() { a = 9; } (); // error: assignment of member 'main()::<lambda()>::a' in read-only object
    std::cout << "a = " << a << std::endl;
    return 0;
}

但是通过值显式捕获全局然后分配给它会产生错误:

#include <iostream>

int a = 10;

int main()
{
    [a]() { a = 9; } (); // assigment of read-only object
    std::cout << "a = " << a << std::endl;
    return 0;
}

我很确定这个错误是正确的行为——为什么隐式捕获会绕过这个错误?我只是在探索新的 C++11 特性,不小心写了第一段代码(没有意识到这应该是一个错误),然后当我认为是局部变量的修改影响了全局时,我感到很惊讶。

由于在 lambda 中分配给按值捕获的变量应该是错误的,因此 GCC 可能会出于优化目的使用对该变量的引用,至少在这种情况下,并且不会检测到错误的分配。

最佳答案

§5.1.2/11:

If a *lambda-expression( has an associated capture-default and its compound-statement odr-uses (3.2) this or a variable with automatic storage duration and the odr-used entity is not explicitly captured, then the odr-used entity is said to be implicitly captured; ...

全局变量具有静态存储持续时间(第 3.7.1 节),因此全局 a 不会隐式按值捕获。不过,您可以在任何地方访问全局变量,所以

[=]() { a = 9; } ();

将按预期将全局 a 设置为 9。

显式捕获全局应该是错误或 UB,因为 §5.1.2/10 说

The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

关于c++ - GCC 在 lambda 函数中通过引用错误地捕获全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9199744/

相关文章:

c++ - while 循环中不保留变量值

c++ - 堆分配与 std::vector

c++ - std::unordered_map 之间的reinterpret_cast

c - 文件格式无法识别;视为链接描述文件

c# - 什么允许匿名无参数委托(delegate)类型有所不同?

python - 使用 lambda 表达式作为函数参数

c++ - 合并 vector 的 vector

c++ - 网格类中损坏的顶点数据

c++ - Callgrind 内联函数

amazon-web-services - 错误 : Expected params. 项目 ['id' ].N 为字符串