如何给 lambda 一个持续时间与 lambda 一样长的内部值?
How to give a lambda an internal value that lasts as long as the lambda?
我想要一个可以在 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 中,这将 return 原始 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
的生命周期是最短的。
我想要一个可以在 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 中,这将 return 原始 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
的生命周期是最短的。