何时在C 11 lambda的定义中捕获需要捕获的变量

When are explicitly-named variable captures necessitated in the definition of a C++11 lambda?

本文关键字:变量 定义 lambda 何时      更新时间:2023-10-16

到现在为止,当查看c++11样式的C lambda表达式时,我将所有这些都放在两个类别中:捕获和非捕捉。

非捕捉lambdas虽然对它们的写作方式有更多的限制,但在如何使用它们的方式上更加灵活 - 它们可以隐式转换为类似的函数销钉类型;他们不鼓励std::function<…>的使用情况,他们的实施范围较小,不太可能引起副作用问题,等等。

但是,捕获的lambda可以以更广泛的方式写。诚然,他们没有赋予我刚才提到的所有这些好处。但是,捕获的Lambda通过从堆栈的进料函数呼叫呼叫插入式DAG的范围内与无数访问周围示波器的访问权分开来弥补了它可以解决的各种问题。

,就我的理解而言。当我使用捕获的lambdas时,当我需要一个和两个变量之间,我倾向于明确参考特定变量:

using lambda_t = std::function<std::add_pointer_t<void>(int)>;
lambda_t lambda_explicit = [&one, &another](int descriptor) {
    return ::mmap(nullptr, one, PROT_READ, MAP_PRIVATE, descriptor, another);
};

…如果有两个以上,我更喜欢(不同等的句法OCD和Laziness(明确命名捕获而避免使用参考形式:

lambda_t lambda_everything = [&](int descriptor) {
    return ::mmap(nullptr, one, PROT_READ, MAP_PRIVATE, descriptor, another);
};

…哪个请注意,更改Lambda捕获的形式并没有改变有关Lambda类型的明显内容 - 例如,呼叫签名是相同的。这是违反直觉的,因为看来捕获作品的许多方式被模糊地指定并且有点特定于特定的,与捕获表达式所提供的详细正式多样性成反比(或者是声明?或声明清单?不确定(您会看到的完整荣耀,如果您转到最后一个链接并向下滚动一点。

我什至没有碰到总体的多数可能性 - 我几乎总是只做:

  1. 根本没有捕获;
  2. 一个或两个明确命名的变量捕获逐参考;或
  3. 所有事物的偶然捕获:[&]

我应该在哪些情况下使用一种形式的捕获?

哪种形式是特殊的,通常要避免?哪些有形的处罚 - 性能,代码大小,潜在的UB或其他任何东西?捕获表格是否有切实和/或简单的好处?

我应该竭尽所能使用一种形式的捕获?

当您局限于使用无状态功能时,捕获不是一个选项,而您仅限于1。通常是将回调注册到C语言API时的情况。

当您想将对象移动到捕获中时,必须将其移至命名捕获中,因此仅限于2。这在C 11中是不可能的。您需要C 14的广义lambda捕获。通用捕获也对不需要传达给外部的最初状态的可变lambdas也很有用(除非明确返回(。

此外,当您希望按值捕获一组变量,而另一种变量按参考捕获时,默认情况下最多可以捕获一个集合,并且必须显式捕获至少一组。也就是说,这可能是一个特殊情况。我不记得曾经需要这个。

我认为没有必要使用默认捕获,但是它可以节省大量的冗余键入。

我更喜欢使用命名捕获的原因,因为我不喜欢全局变量。它给出了lambda代码的范围。

,如果有许多变量,并且许多lambdas仅访问带有未命名的语法的一些变量,那么审核代码很快就变得不可能。好的,如果您的功能很小,有3个本地变量,那么很容易接受lambda可以看到所有三个变量,但是如果您有10个当地人,则在重新访问代码时浪费时间,试图了解哪个三个变量lambda实际上修改了。