非本地lambda和捕获变量 - “块范围”的含义

时间:2013-10-13 12:01:31

标签: c++ c++11 lambda

我正在玩c ++ 11 lambdas并找到了一个我无法理解的例子。根据标准:

  

一个lambda表达式,其最小的封闭范围是块范围(3.3.3)是一个局部lambda表达式;任何   其他lambda-expression在其lambda-introducer中不应该有一个capture-list

所以,我创造了一些简单的例子:

int a = 10;
auto x  = [a] { return 1;};
int main() {
    int k = 5;
    auto p = [k]{ return k; };
    return 0;
}

ideone中的代码:http://ideone.com/t9emu5

由于在非块范围内捕获变量(或至少认为auto x = ... part不在块范围内),我期望此代码无法编译。但代码正在编译 - 可以吗?

如果没问题 - 块范围是什么?

(我不确定我使用的编译器版本,因为目前我只能访问ideone站点。

感谢您的解释!

1 个答案:

答案 0 :(得分:12)

看起来这是一个编译器扩展。 g ++ 4.8.1在发出警告的同时编译它:

  

警告:捕获具有非自动存储持续时间的变量'a'[默认启用]

clang ++ 3.4无法编译:

  

错误:无法捕获'a',因为它没有自动存储持续时间

两者都指[expr.prim.lambda] / 10

  

使用通常的非限定名称查找规则(3.4.1)查找捕获列表中的标识符;每个这样的查找都应该找到一个变量,其自动存储持续时间在本地lambda表达式的到达范围内声明。

似乎他们没有另外检查lambda的封闭范围,我可以想象它是多余的(在非块/命名空间范围内没有自动存储持续时间的变量名称)。


块范围在[basic.scope.block] / 1

中定义
  

块(6.3)中声明的名称是该块的本地名称;它有块范围。

一个块定义为:

  

因此,可以在需要一个语句时使用多个语句,提供复合语句(也称为“块”)。

     

复合声明:
  { statement-seq opt }

所以你是正确的,你的全局声明的lambda在块范围内不是