如何让C++类构造函数每次调用时创建不同的Lambda表达式?
问题分析与解决方案
问题原因
你遇到的核心问题是无捕获lambda的特性:无捕获的lambda表达式会被编译器转换为一个全局函数实体,所有由同一个lambda定义生成的闭包对象都会关联到这个函数。而lambda内部的static int i和普通全局函数中的static变量完全一致——整个程序生命周期内仅初始化一次,所有调用都会共享这个变量。
在MSVC中,无捕获lambda可以隐式转换为函数指针,std::function<void()>最终存储的是这个全局函数的指针,因此两个a实例的func指向的是同一个函数,调用时自然会共享static变量的状态,导致输出1和2。
解决方案
要实现每个实例的func拥有独立状态,有两种常用方式:
方案1:将状态作为类成员,lambda捕获this
把计数器i定义为类的私有成员,让lambda捕获当前实例的this指针,这样每个实例的lambda操作的是自己的成员变量:
#include <iostream> #include <functional> class a { public: a() : i(0) { func = [this] { i++; std::cout << i << std::endl; }; } std::function<void()> func; private: int i; }; int main() { a a1; a1.func(); a a2; a2.func(); }
方案2:让lambda捕获局部变量副本并声明mutable
在构造函数中定义局部计数器,通过值捕获将其存入lambda闭包,同时需要给lambda加上mutable修饰符(默认lambda是const的,无法修改捕获的值),这样每个lambda实例会持有独立的计数器副本:
#include <iostream> #include <functional> class a { public: a() { int i = 0; func = [i]() mutable { i++; std::cout << i << std::endl; }; } std::function<void()> func; }; int main() { a a1; a1.func(); a a2; a2.func(); }
上述两种方案运行后都会输出你预期的:
1 1
内容的提问来源于stack exchange,提问作者Ivan Venkov
相关产品推荐
相关产品推荐

