C++ Can a C++;11 lambda捕获文件范围变量?

C++ Can a C++;11 lambda捕获文件范围变量?,c++,c++11,lambda,C++,C++11,Lambda,ISO C++11规范第5.1.2 p10节规定: 捕获列表中的标识符是使用常规规则查找的 用于非限定名称查找(3.4.1);每次查找都应找到一个 变量中声明了自动存储持续时间 局部lambda表达式的作用域。实体(即变量或 如果它出现在 lambda表达式的捕获列表 这似乎意味着lambda无法捕获文件范围变量。例如,此程序应该是非法的: #include <iostream> int x = 13; int main() { auto l = [](){ return x

ISO C++11规范第5.1.2 p10节规定:

捕获列表中的标识符是使用常规规则查找的 用于非限定名称查找(3.4.1);每次查找都应找到一个 变量中声明了自动存储持续时间 局部lambda表达式的作用域。实体(即变量或 如果它出现在 lambda表达式的捕获列表

这似乎意味着lambda无法捕获文件范围变量。例如,此程序应该是非法的:

#include <iostream>

int x = 13;

int main()
{
  auto l = [](){ return x; };

  std::cout << l() << std::endl;

  return 0;
}
但是
clang
3.0崩溃:

$ clang --version
Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
Target: i386-pc-linux-gnu
Thread model: posix
$ clang -std=c++11 lambda.cpp 
0  libLLVM-3.0.so.1 0xb70a59e8
1  libLLVM-3.0.so.1 0xb70a5f34
2                   0xb775d400 __kernel_sigreturn + 0
3  clang            0x0869f2e9 clang::Sema::DeduceAutoType(clang::TypeSourceInfo*, clang::Expr*, clang::TypeSourceInfo*&) + 73
<snip>
$clang--版本
UbuntuClang版本3.0-6ubuntu3(tags/RELEASE_30/final)(基于LLVM 3.0)
目标:i386 pc linux gnu
线程模型:posix
$clang-std=c++11 lambda.cpp
0 libLLVM-3.0.so.1 0xb70a59e8
1 libLLVM-3.0.so.1 0xb70a5f34
2 0xb775d400内核返回+0
3 clang 0x0869f2e9 clang::Sema::演绎自动类型(clang::TypeSourceInfo*,clang::Expr*,clang::TypeSourceInfo*&)+73

我的程序是否非法?如果它是非法的,那么禁止捕获文件范围变量的理由是什么?

为了查找名称,lambda的主体被视为在lambda表达式的上下文中。也就是说,名称查找就像在lambda之外使用名称一样进行。见[expr.prim.lambda]/7。例如:

#include <iostream>

int x = 13;
int y = 0;

int main()
{
  static int y = 42;
  int z = 1729;

  auto l = [/*forget about the capture for a moment*/]()
  { return x+y+z; };
  // find the names x,y,z as if they had been mentioned outside the lambda
  // find the locals y, z and the global x

  std::cout << l() << std::endl;

  return 0;
}

在您的示例中,您没有捕获
x
,您只是使用它。毕竟,它是一个全球性的(所以你可以使用它,因为它是可见和可访问的)。请参阅“如果它是非法的,那么禁止捕获文件范围变量的理由是什么?”您只需要捕获自动变量,因此只能捕获自动变量。谢谢你的解释!如果您将您的评论合并到一个简短的答案中,我会接受。clang崩溃的原因很简单,因为lambda支持直到3.1才在clang中完成。这在一个支持lambda的版本中运行良好。实际上,如果捕获是按值进行的,那么您的“嗯-哦”就可以了。我认为,当您可以通过添加一个字符显式捕获所有字符时,标准没有理由指定默认值。@SteveJessop是的,我指的是不捕获
z
,类似于不捕获
x
y
。该标准允许访问自动变量而不捕获它们,但这会导致生存期问题(以及与引用对象的位置相关的等效实现问题)。因此,需要捕获它们,然后有几种方法可以做到这一点。
#include <iostream>

int x = 13;
int y = 0;

int main()
{
  static int y = 42;
  int z = 1729;

  auto l = [/*forget about the capture for a moment*/]()
  { return x+y+z; };
  // find the names x,y,z as if they had been mentioned outside the lambda
  // find the locals y, z and the global x

  std::cout << l() << std::endl;

  return 0;
}
int main()
{
  static int y = 42;

  std::function<int()> f;
  {
    int z = 1729;

    f = [](){ return x+y+z; }; // imagine we could do this
  }

  std::cout << f() << std::endl; // uh-oh!

  return 0;
}
int main()
{
  int x = 42;
  constexpr int y = 1789;

  auto l = []() -> int
  {
      decltype(x) my_var = 100;  // no odr-use of `x`
      return my_var*y;           // no odr-use of `y`
  };

  std::cout << l() << std::endl;

  return 0;
}