【问题标题】:Lambda CapturesLambda 捕获
【发布时间】:2017-10-18 12:12:23
【问题描述】:

我总是对 lambda 捕获感到困惑,我不知道变量是通过引用还是按值捕获的。例如,如果我有[a],我不知道a 是按值还是按引用捕获的。

我认为获得它的简单方法是通过示例。因此,让我们为每种情况使用一个(如果有更多表达同一事物的方式,则更多):

捕获:

  • 什么都没有
  • 全部参考
  • 全部按值
  • r1, r2 引用。没有别的了。
  • v1, v2 按值。没有别的了。
  • r1, r2 引用。按价值休息。
  • v1, v2 按值。参考休息。
  • r1r2 按引用、v1v2 按值。没有别的了。

让我们完全忽略this,因为那是另一包蠕虫。

【问题讨论】:

  • 请注意所有规则都非常详细here
  • 每次我写或读一个 lambda 捕获并且必须搜索网络时,我都在真正地问自己。还没有找到一个简单干净的解释。我认为这将是一个有价值的帖子。
  • @NathanOliver 是的,我知道,但我仍然不知道 [a] 是按引用还是按值。事实上,我只扫描页面。但老实说,当我想知道一个简单的答案时,我既没有意愿也没有时间阅读复杂的描述。我不知道,也许只有我一个人。无论如何,我认为应该存在关于 SO 的帖子。
  • 当然。它不在这里的事实意味着它应该是:-) 我刚刚添加了链接,所以如果人们真的想深入了解这个主题,他们有一个很好的参考。
  • 这是要进入c++-faq吗?

标签: c++ lambda closures


【解决方案1】:

简而言之:

[]{ }          // do not capture anything
[foo]{ }       // capture `foo` by value
[&foo]{ }      // capture `foo` by reference
[foo, &bar]{ } // capture `foo` by value, `bar` by reference
[=, &foo]{ }   // capture everything by value, `foo` by reference
[&, foo]{ }    // capture everything by reference, `foo` by value

在 C++14 中,您还拥有通用 lambda 捕获

[i=0]{ }  // create closure with `i` data member initialized to `0`
[i=j]{ }  // create closure with `i` data member initialized to `j`
[i{0}]{ } // create closure with `i` data member initialized to `0`
[i{j}]{ } // create closure with `i` data member initialized to `j`

// create closure with `uptr` data member initialized to `std::move(uptr)`
[uptr = std::move(uptr)]{ } 

// create closure with `foo` reference data member initialized to `something`
[&foo = something]{ }

如果您想通过引用或按值有条件地捕获,您可以使用通用 lambda 捕获 来实现某种“完美转发捕获”:"capturing perfectly-forwarded objects in lambdas"


让我们完全忽略this,因为那是另一包蠕虫。

[this]{ }  // capture `this` by value (the pointer)
[*this]{ } // store a copy of `*this` inside the closure

【讨论】:

  • 另外,不是成员捕获(在“一切”捕获中),而是捕获this
【解决方案2】:
| Capture                                       | Syntax             |
| --------------------------------------------- | ------------------ |
| nothing                                       | []                 |
| all by reference                              | [&]                |
| all by value                                  | [=]                |
| r1, r2 by reference. Nothing else.            | [&r1, &r2]         |
| v1, v2 by value. Nothing else.                | [v1, v2]           |
| r1, r2 by reference. Rest by value.           | [=, &r1, &r2]      |
| v1, v2 by value. Rest by reference.           | [&, v1, v2]        |
| r1, r2 by ref, v1, v2 by value. Nothing else. | [v1, v2, &r1, &r2] |

规则很简单:前面是&,通过引用捕获。仅名称,按值捕获。

默认值:= 全部为值,& 全部为引用。从“全部”中排除的内容使用上面的简单规则。


完整的规则可以在cppreference阅读。

【讨论】:

    【解决方案3】:
    • 什么都没有

      []
      
    • 全部参考

      [&]
      
    • 全部按值

      [=]
      
    • r1, r2 引用。没有别的了。

      [&r1, &r2]
      
    • v1, v2 按值。没有别的了。

      [v1, v2]
      
    • r1, r2 引用。按价值休息。

      [=, &r1, &r2]
      
    • v1, v2 按值。参考休息。

      [&, v1, v2]
      
    • r1r2 按引用、v1v2 按值。没有别的了。

      [&r1, &r2, v1, v2]
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      • 2016-03-10
      • 2017-05-28
      • 1970-01-01
      相关资源
      最近更新 更多