Lambda 表达式到达范围

kes*_*vic 2 c++ lambda

在学校的面向对象编程课上,我们学习了C++中的Lambda表达式,教授明确表示捕获Lambda表达式内变量的到达范围只是内层的封装范围。

考虑到讲座,我的结论是下面的代码不应该起作用,因为变量bc是在 lambda 自身范围的最内部封装范围之外定义的。不幸的是,它确实有效。

我曾尝试使用g++clang编译代码,并且两者都产生了正确的结果?结果。

我的问题是这是否是未定义的行为,或者编译器正在尝试用它做一些事情,或者我们可能被错误地教导?

int main(int argc, char const *argv[])
{
    int a = 5;
    {
        int b = 10;
        {
            int c = 15;
            {
                int a = 10;
                auto f = [&]()
                {
                    std::cout << a << b << c;
                };
                f();
                std::cout << a;
            }
        }
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

另外,在和助理教授一起练习Lambda表达式时,他告诉我们尝试编译以下.cpp文件。

int main(int argc, char *argv[])
{
  int x = 7;
  std::function<void()> foo;
  {
    int z = 19;
    foo = [x, z]() mutable
    {
      x = 5;
      std::cout << x << " " << z << std::endl;
    };
  }
  foo();
  std::cout << x;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译后,他表示这种情况不应该发生,但编译器仍然这样做,并且xlambda 表达式不应该访问该变量。

sha*_*hay 5

您的示例代码似乎是有效的,至少对于 C++17 来说是这样(我猜其他的,但 17 是我手头上碰巧有的标准)。关于 lambda 捕获的第 8.1.5.2 节说(强调我的):

\n
\n

最小封闭作用域是块作用域 (6.3.3) 的 lambda 表达式是局部 lambda 表达式;任何\n其他 lambda 表达式在其 lambda 引入器中不应有 capture-default 或 simple-capture。本地 lambda 表达式的到达作用域是一组封闭作用域,直至并包括最内层的封闭函数及其参数。[ 注意:此到达范围包括任何介入的 lambda 表达式。\n\xe2\x80\x94 尾注 ]

\n
\n

所以看起来编译器的行为符合标准的预期

\n