【问题标题】:Non local lambda and capturing variables - what does "block scope" means非本地 lambda 和捕获变量 - “块范围”是什么意思
【发布时间】:2013-10-13 12:01:30
【问题描述】:

我目前正在使用 c++11 lambda,发现了一个我无法理解的示例。根据标准:

最小封闭范围是块范围(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 站点。

感谢您的解释!

【问题讨论】:

  • 那么,什么是非块范围?
  • @DanielFrey 嗯?块是复合语句,命名空间当然不是块。参见 [basic.scope.block]/1 和 [stmt.block]
  • @DyP 对不起,我弄糊涂了。你完全正确!
  • @KerrekSB:不,我不这么认为。这个问题是特定于 lambda 捕获的。
  • +1:听起来可能是 GCC 错误,尤其是当 clang 发现代码存在另一个问题时。

标签: c++ c++11 lambda


【解决方案1】:

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

警告:以非自动存储持续时间捕获变量“a”[默认启用]

clang++3.4 不能编译这个:

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

均指 [expr.prim.lambda]/10

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

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


块作用域在 [basic.scope.block]/1 中定义

在块 (6.3) 中声明的名称是该块的本地名称;它有块作用域。

而一个block定义为:

为了可以在需要一个语句的地方使用多个语句,提供了复合语句(也称为“块”)。

     复合语句:
{ 语句序列opt }

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

【讨论】:

  • 补充:你可以使用编译标志-pedantic-errors(除了-std=c++11)让GCC拒绝它,我推荐它(还有-Wall -Wextra)。 Ideone 不允许您指定编译器选项,但例如Coliru 可以(GCC Explorer 也可以,但它只编译(并显示程序集输出),不链接和运行)。 (有关更多在线 C++ 编译器,请参见 isocpp.org/get-started。)
  • @gx_ 这似乎是错误的。我使用-Wall -Wextra -Wpedantic 编译,并且从未在我的代码中被告知此错误(这可能是由于将 lambda 移出本地范围造成的),跨越 g++ 版本 5 和现在的 6.1。毫不奇怪,添加-pedantic-errors 并没有改变这一点。 g++ 只是没有警告我。我想我需要更频繁地向clang++ 询问第二意见......叹息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多