如何为 lambda 提供一个与 lambda 一样长的内部值

How to give a lambda an internal value that lasts as long as the lambda?

本文关键字:lambda 一样 内部 一个      更新时间:2023-10-16

我想要一个变量,我可以在 lambda 中修改而不影响封闭范围。行为如下:

std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
{
  auto sum = 0;
  std::for_each(vec.begin(), vec.end(), [sum](int value) mutable
  {
    sum += value;
    std::cout << "Sum is up to: " << sum << '/n';
  });
}

但是,我希望能够在不声明 lambda 外部的 sum 变量的情况下做到这一点。像这样:

std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
std::for_each(vec.begin(), vec.end(), [auto sum = 0](int value) mutable
{
  sum += value;
  std::cout << "Sum is up to: " << sum << '/n';
});

因此sum仅在 lambda 内部可见,在封闭范围内不可见。在 C++11/14 中可能吗?

C++14 引入了广义 Lambda 捕获,允许您做您想做的事。

捕获将从 init 表达式的类型推断出来,就像通过 auto 一样。

[sum = 0] (int value) mutable {
    // 'sum' has been deduced to 'int' and initialized to '0' here.
    /* ... */
}
如果您

坚持使用 C++11(并且无法使用 C++14 的 lambda 捕获表达式,请参阅 @Snps' 的答案),那么您可以在 lambda 中声明一个静态变量,就像在任何其他函数中所做的那样。示例如下:

#include <algorithm>
#include <vector>
#include <iostream>
int main()
{
    std::vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    std::for_each(vec.begin(), vec.end(), [](int value)
    {
        static decltype(vec)::value_type sum{};
        sum += value;
        std::cout << "Sum is up to: " << sum << 'n';
    });
}
至少在我看来

,有更好的方法可以做到这一点。您正在使用std::for_each,但用它来模仿std::accumulate。后者是手头工作的明确选择:

#include <numeric>
#include <iostream>
#include <vector>
int main(){
    std::vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    std::accumulate(vec.begin(), vec.end(), 0, [](int sum, int val) {
        sum += val;
        std::cout << "sum is up to: " << sum << "n";
        return sum; });
}

我不确定这对你来说是否真的重要,但这不需要 C++11 以外的任何功能。

如果 C++14 不可用,您可以将所有内容包装在 lambda 中,这将返回原始 lambda,并立即调用它。

std::for_each(vec.begin(), vec.end(), []()
{
    auto sum = 0;
    return [sum](int value) mutable
    {
        sum += value;
        std::cout << "Sum is up to: " << sum << 'n';
    };
}());

这样,临时sum的生存期就最短了。