为什么有时不需要在Lambda中捕获const变量?

s3rvac:

考虑以下示例:

#include <cstdlib>

int main() {
    const int m = 42;
    [] { m; }(); // OK

    const int n = std::rand();
    [] { n; }(); // error: 'n' is not captured
}

为什么我需要n在第二个Lambda中捕获而不是m在第一个Lambda中捕获我检查了C ++ 14标准中的5.1.2节(Lambda表达式),但找不到原因。您能指出我对此段的解释吗?

更新:我在GCC 6.3.1和7(主干)中都观察到了此行为。在这两种情况下(variable 'm' cannot be implicitly captured in a lambda with no capture-default specified),Clang 4.0和5(主干)均失败,并出现错误

MM:

对于处于块范围的lambda,即使未捕获到满足范围内某些条件的变量,也可以在lambda内部以有限的方式使用它们。

粗略地讲,达到范围包括包含lambda的函数局部的任何变量,该变量将在定义lambda的范围内。因此mn在上面的示例中,这包括

具体来说,“某些标准”和“有限的方式”(从C ++ 14开始):

  • 在lambda内部,不得对该变量进行odr-used,这意味着除以下内容外,不得对该变量进行任何操作:
    • 出现为舍弃值表达式(m;是其中之一),或者
    • 获取其值。
  • 该变量必须是:
    • 一个A const,非volatile整数或枚举,其初始值设定项是一个常量表达式,或者
    • A constexpr,非volatile变量(或此类的子对象)

对C ++ 14的引用:[expr.const] /2.7,[basic.def.odr] / 3(第一句话),[expr.prim.lambda] / 12,[expr.prim.lambda] / 10。

正如其他评论/答案所建议的那样,这些规则的基本原理是,编译器需要能够“合成”无捕获的lambda作为独立于块的自由函数(因为此类事情可以转换为指针,功能);如果知道变量将始终具有相同的值,则即使引用变量也可以执行此操作,也可以重复此过程以独立于上下文获取变量的值。但是,如果变量可能不时有所不同,或者例如需要变量的地址,则无法执行此操作。


在您的代码中,n已通过非常量表达式初始化。因此n,未经捕获就不能在lambda中使用。

m是通过常量表达式初始化的42,因此它确实满足“某些条件”。舍弃值表达式不会使用该表达式,因此m;可以在不m被捕获的情况下使用它。gcc是正确的。


我会说这两个编译器之间的区别是clang考虑m;使用odr-use m,但gcc不会。[basic.def.odr] / 3的第一句话很复杂:

一种可变x其名称显示为潜在评估表达exODR使用的ex除非施加左值到右值转换到x产率的常量表达式不调用任何非平凡函数,并且如果x是一个对象,ex是的一个元素表达式的潜在结果集e,其中将左值到右值转换应用于e,或者e是舍弃值表达式。

但是,仔细阅读后,它确实特别提到了舍弃值表达式不会使用该表达式。

C ++ 11的[basic.def.odr]版本最初不包含舍弃值表达式大小写,因此在已发布的C ++ 11下clang的行为将是正确的。但是,C ++ 14中出现的文本被视为针对C ++ 11的缺陷(问题712),因此,即使在C ++ 11模式下,编译器也应更新其行为。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Java

为什么Final变量不需要在Java的main方法中初始化?

来自分类Java

为什么Java 8中的lambda表达式需要在其中使用变量才能使用“最终”修饰符,而在使用方法引用时却不需要?

来自分类Java

Spring Boot->为什么我不需要在服务中捕获异常?

来自分类Dev

为什么有时需要在`data.frame()`中将`.`括在`do`中的命名参数中?

来自分类Dev

为什么const变量不需要在C中初始化?

来自分类Dev

为什么C ++变量是指针时不需要正确定义?

来自分类Dev

为什么执行AsyncTask时不需要捕获TimeoutException?

来自分类Dev

为什么我有时需要使用JSON.stringify而有时不需要

来自分类Dev

在node.js / Express中,为什么在next()之后有时需要返回语句,而有时却不需要?

来自分类Dev

为什么我们不需要在React中绑定箭头功能?

来自分类Dev

为什么在比较变量时需要取消引用变量,而在进行算术时却不需要?

来自分类Dev

为什么在使用__syncthreads时我们不需要使用volatile变量

来自分类Dev

为什么我们不需要在Python函数中实际使用全局变量之前就定义它们?

来自分类Dev

为什么我们不需要在self()中包含self?

来自分类Dev

为什么不需要将此堆栈变量移至闭包中?

来自分类Dev

为什么在Kotlin中不需要在Room中的查询功能添加suspended关键字?

来自分类Dev

为什么我不需要在cmake中调用`add_test`?

来自分类Dev

为什么在结束“循环”时“中断”不需要分号?

来自分类Dev

为什么对象不需要时Java中的数组需要具有预定义的长度?

来自分类Dev

为什么jq有时需要过滤器表达式,而有时则不需要过滤器表达式?

来自分类Dev

为什么我不需要在Mac OS X中设置CLASSPATH和JAVA_HOME?

来自分类Dev

为什么包含main方法的类不需要在Java中公开?

来自分类Dev

为什么iter()需要lambda函数的&,而本例中的range却不需要

来自分类Dev

为什么不需要在构造函数中指定变量?

来自分类Dev

为什么有时需要在将对象作为参数传递之前创建变量

来自分类Dev

为什么QEMU的hostfwd选项有时需要root访问,而有时却不需要root访问

来自分类Dev

为什么我不需要在C#中实现这些抽象功能?

来自分类Dev

为什么“尝试/捕获”中的命令有时需要-ErrorAction停止,而有时则不需要?

来自分类Dev

PHP:为什么在 php 变量前不需要 $?

Related 相关文章

  1. 1

    为什么Final变量不需要在Java的main方法中初始化?

  2. 2

    为什么Java 8中的lambda表达式需要在其中使用变量才能使用“最终”修饰符,而在使用方法引用时却不需要?

  3. 3

    Spring Boot->为什么我不需要在服务中捕获异常?

  4. 4

    为什么有时需要在`data.frame()`中将`.`括在`do`中的命名参数中?

  5. 5

    为什么const变量不需要在C中初始化?

  6. 6

    为什么C ++变量是指针时不需要正确定义?

  7. 7

    为什么执行AsyncTask时不需要捕获TimeoutException?

  8. 8

    为什么我有时需要使用JSON.stringify而有时不需要

  9. 9

    在node.js / Express中,为什么在next()之后有时需要返回语句,而有时却不需要?

  10. 10

    为什么我们不需要在React中绑定箭头功能?

  11. 11

    为什么在比较变量时需要取消引用变量,而在进行算术时却不需要?

  12. 12

    为什么在使用__syncthreads时我们不需要使用volatile变量

  13. 13

    为什么我们不需要在Python函数中实际使用全局变量之前就定义它们?

  14. 14

    为什么我们不需要在self()中包含self?

  15. 15

    为什么不需要将此堆栈变量移至闭包中?

  16. 16

    为什么在Kotlin中不需要在Room中的查询功能添加suspended关键字?

  17. 17

    为什么我不需要在cmake中调用`add_test`?

  18. 18

    为什么在结束“循环”时“中断”不需要分号?

  19. 19

    为什么对象不需要时Java中的数组需要具有预定义的长度?

  20. 20

    为什么jq有时需要过滤器表达式,而有时则不需要过滤器表达式?

  21. 21

    为什么我不需要在Mac OS X中设置CLASSPATH和JAVA_HOME?

  22. 22

    为什么包含main方法的类不需要在Java中公开?

  23. 23

    为什么iter()需要lambda函数的&,而本例中的range却不需要

  24. 24

    为什么不需要在构造函数中指定变量?

  25. 25

    为什么有时需要在将对象作为参数传递之前创建变量

  26. 26

    为什么QEMU的hostfwd选项有时需要root访问,而有时却不需要root访问

  27. 27

    为什么我不需要在C#中实现这些抽象功能?

  28. 28

    为什么“尝试/捕获”中的命令有时需要-ErrorAction停止,而有时则不需要?

  29. 29

    PHP:为什么在 php 变量前不需要 $?

热门标签

归档