我正在玩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站点。
感谢您的解释!
答案 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在块范围内不是。