Lambda捕获

5
我总是被lambda捕获所迷惑,不知道一个变量是按值还是按引用捕获的。例如,如果我有[a],我不知道a是按值还是按引用捕获的。
我认为一个简单的方法是通过例子来理解每种情况(如果有多种表达方式,则需要更多例子):
捕获:
- 无 - 全部按引用 - 全部按值 - r1,r2按引用。其他没有。 - v1,v2按值。其他没有。 - r1,r2按引用。其余按值。 - v1,v2按值。其余按引用。 - r1,r2按引用,v1,v2按值。其他没有。
让我们完全忽略this,因为它是另一个问题。

2
请注意,所有规则都在这里详细说明:http://en.cppreference.com/w/cpp/language/lambda#Lambda_capture。 - NathanOliver
1
每次我写或读一个lambda捕获并需要在网上搜索时,我都会真正地问自己。我还没有找到一个简单清晰的解释。我认为这将是一个有价值的帖子。 - bolov
@NathanOliver 是的,我知道,但我仍然不知道 [a] 是按引用还是按值传递。事实上,我只是浏览页面。但说实话,当我想知道一个简单的答案时,我既没有意愿也没有时间去阅读复杂的描述。我不知道,也许只有我这样。无论如何,我认为 SO 上应该存在这样的帖子。 - bolov
1
当然。事实上它不在这里意味着它应该在 :-) 我只是添加了链接,所以如果人们真的想深入了解这个主题,他们有一个很好的参考。 - NathanOliver
哦,我以为这是你的意图,因此它的措辞方式。它看起来确实是为了包容而设计的 :) - StoryTeller - Unslander Monica
显示剩余4条评论
3个回答

13

简而言之:

[]{ }          // 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捕获来实现某种“完美转发捕获”。这篇文章介绍了如何在lambda表达式中“捕获完美转发的对象”:"capturing perfectly-forwarded objects in lambdas"
请忽略`this`,因为那是另一个讨论话题。
[this]{ }  // capture `this` by value (the pointer)
[*this]{ } // store a copy of `*this` inside the closure

此外,与其捕获成员(在“everything”捕获中),而是捕获this - Jarod42

8
| 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上阅读。


4
  • 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 reference, v1, v2 by value. Nothing else.

    [&r1, &r2, v1, v2]
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接