我想创建一个生成lambda的函数,其中每个lambda都有自己的静态变量。但是,与我的想法相反,静态变量似乎在实例之间共享。例如,
#include <iostream>
auto make_lambda(){
return [](){
static auto count = 0;
return count++;
};
}
int main() {
auto a = make_lambda();
auto b = make_lambda();
std::cout << &a << ", " << a() << std::endl;
std::cout << &b << ", " << b() << std::endl;
}
返回
0x7ffc229178df, 0
0x7ffc229178de, 1
因此a
和b
似乎是唯一的实例,但它们共享该静态计数。我以为我会看到并且确实想看到类似
0x7ffc229178df, 0
0x7ffc229178de, 0
确保每个lambda都有自己的静态变量的最简单方法是什么?
答案 0 :(得分:11)
抛弃静态变量并使用扩展的lambda捕获:
#include <iostream>
auto make_lambda(){
return [count = 0]() mutable {
return count++;
};
}
如果您希望不同的Lambda实例与其各自的副本共享状态,而不是在它们之间共享状态,则可以改用std::shared_ptr
:
auto make_lambda(){
return [count = std::make_shared<int>(0)]() mutable {
return (*count)++;
};
}
答案 1 :(得分:6)
您可以利用以下事实:实例化函数及其所包围的模板化实体在函数中定义了自己的静态变量副本。将make_lambda
变成模板...
template<int>
static auto make_lambda(){
return [](){
static auto count = 0;
return count++;
};
}
...将为TU唯一的每个新模板参数生成一个新的静态变量(由于功能模板本身为static
):
auto a = make_lambda<0>();
auto b = make_lambda<1>();
std::cout << &a << ", " << a() << std::endl;
std::cout << &b << ", " << b() << std::endl;
这不是您想要的语法,但是可以完成工作。如果您不介意涉及预处理器和潜在的编译器扩展,则可以使用带有辅助宏的简单函数调用语法。
#define make_lambda() make_lambda<__COUNTER__>()
其中__COUNTER__
是一个GCC扩展名,每次在任何单个TU中需要扩展时,它都会扩展为新的数字。
答案 2 :(得分:3)
您可以按值将变量传递给lambda。 此外,您必须使lambda可变,以便能够在执行期间修改该值。通常,Labda就像const方法。
auto make_lambda(){
int count = 0;
return [count]() mutable {
return count++;
};
}