8

我目前正在使用 c++11 lambdas 并找到一个我无法理解的示例。根据标准:

最小封闭范围是块范围 (3.3.3) 的 lambda 表达式是本地 lambda 表达式;任何其他 lambda-expression 在其 lambda-introducer 中都不应有捕获列表

所以,我创建了一个简单的例子:

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 = ... 部分不在块范围内)。但是代码正在编译 - 可以吗?

如果可以 - 块范围是什么?

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

感谢您的解释!

4

1 回答 1

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不在块范围内。

于 2013-10-13T12:15:06.967 回答