ISO C++11规范的第5.1.2节p10规定:
捕获列表中的标识符使用未限定名称查找(3.4.1)的常规规则进行查找;每次这种查找都应在局部Lambda表达式所处的可达范围内找到一个带有自动存储期的变量。如果实体(即变量或this指针)出现在Lambda表达式的捕获列表中,则称其为显式捕获。
这似乎意味着Lambda无法捕获文件作用域变量。例如,下面的程序是非法的:
#include <iostream>
int x = 13;
int main()
{
auto l = [](){ return x; };
std::cout << l() << std::endl;
return 0;
}
然而,
g++
4.7.1却输出了我所期望的结果:$ g++ --version
g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -std=c++11 lambda.cpp
$ ./a.out
13
但是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>
我的程序是否非法?如果非法的话,捕获文件作用域变量的禁令是基于什么理由的?
x
,只是使用了它。毕竟它是全局变量(所以你可以使用它,因为它是可见和可访问的)。参见这个问题。 - dyp