C++ 如何给lambda一个持续时间与lambda相同的内部值?

C++ 如何给lambda一个持续时间与lambda相同的内部值?,c++,c++11,lambda,c++14,C++,C++11,Lambda,C++14,我希望有一个变量可以在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

我希望有一个变量可以在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';
  });
}
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';
    });
}
#包括
#包括
#包括
int main()
{
向量向量={1,2,3,4,5,6,7,8,9,0};
std::for_each(vec.begin()、vec.end()、[](int值)
{
静态decltype(vec):值\类型和{};
总和+=数值;

std::cout至少在我看来,有更好的方法可以做到这一点。您使用
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; });
}
#包括
#包括
#包括
int main(){
向量向量={1,2,3,4,5,6,7,8,9,0};
标准::累加(向量开始(),向量结束(),0,[](整数和,整数值){
sum+=val;

如果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';
    };
}());
std::for_each(vec.begin()、vec.end()、[]()
{
自动求和=0;
返回[和](整数值)可变
{
总和+=数值;

std::无法删除
自动
并将
11
替换为
14
,您就可以开始了。@KerrekSB太棒了!谢谢:)在我看来,“sum”的初始化在每次运行中只会发生一次。在本例中,使用“main”并不重要,但在一般情况下这是一个问题。此外,statics中断可重入性(并且可以限制优化)。请参阅@greggo不确定我是否理解您所说的“在我看来,“sum”的初始化在每次运行时只会发生一次。”
sum
仅在第一次调用时初始化,就像常规函数中的任何静态变量一样。感谢您提供的链接……因此,如果您将其放在名为“sumvec”而不是“main”的func中,对“sumvec”的第二次调用将不起作用,因为“sum”只初始化了一次。@greggo好吧,这取决于一个人到底想实现什么。我同意在这方面使用捕获表达式更好,因为你可以“重用”同一个lambda(即从闭包生成的对象)。我认为它超出了这一范围。每次调用“sumarr”在这两种情况下都会构造一个新的lambda对象,但静态变量对所有实例都是通用的。在调用之间变化的静态局部变量的用途非常有限,我不会将其称为其中之一。有趣的是,这是我第一次看到有人以该名称引用此功能。通常我会看到init capture或“广义lambda capture”@T.C.你说得对,它通常是指那些名字。经过编辑。这个例子只是为了说明目的。累加不太合适,而且这个名字在复习时会让人混淆。不过最好记住,算法中还有其他函数。在尝试做某事之前,我并不总是检查。@Kian:但是你问的是什么r是一个值,在其中从一个lambda调用到下一个lambda调用累积(某物)…我可以看到“一个变量如何保留前一个调用的值并对其应用一个操作”是一种累加器。例如,如果我想要一个索引,我会在每次迭代中累加并添加一个。但是,std::acculate返回累加器。如果你想要使用索引,因为你需要从lambda中索引到其他结构中,那么这个名称是误导性的。累加是一个实现细节,我不想累加6个月后阅读代码的人可能会想,为什么要调用累积并放弃返回值。