如何在C++中复用"闭包生成器"?
C++中闭包生成器的复用问题
C++中的闭包表现和其他具备GC、会延长捕获变量生命周期的编程语言不同。比如编写如下代码:
auto generator() { int common = 0; auto adder1 = [=]() mutable { ++common; return common; }; auto adder2 = [=]() mutable { ++common; return common; }; return make_pair(adder1, adder2); } int main() { auto pair = generator(); auto a1 = pair.first; auto a2 = pair.second; cout << a1() << " " << a2() << "\n"; return 0; }
我们期望得到输出1 2,因为认为common是adder1和adder2共享的“词法环境”。但实际运行结果是1 1,原因是common被按值捕获,每个闭包都持有独立的common副本,彼此的修改互不影响。
解决该问题的一种方案是将common声明为static,但static会以不符合预期的方式延长common的生命周期,因此更倾向于另一种方案:使用C++14的初始化lambda捕获创建闭包生成器,通过引用捕获common:
auto generator = [common = 0]() mutable { auto adder1 = [&]() { ++common; return common; }; auto adder2 = [&]() { ++common; return common; }; return make_pair(adder1, adder2); };
此时代码运行正常,输出1 2。这类用于初始化adder的生成器我称之为“闭包生成器”,它们通常不是我们所需的特定闭包。
但这种方案存在复用问题:无法为不同的(adder1, adder2)对创建独立的common。比如调用生成器的代码如下:
int main() { auto pair1 = generator(); auto pair2 = generator(); auto a1 = pair1.first; auto a2 = pair1.second; auto a3 = pair2.first; auto a4 = pair2.second; a1(); a1(); a1(); a2(); a2(); a2(); a2(); a3(); a4(); cout << a1() << " " << a2() << " " << a3() << " " << a4() << "\n"; return 0; }
实际输出为10 11 12 13,而非期望的8 9 3 4——因为生成器本身是一个闭包,所有调用生成的pair1和pair2会共用同一个common实例。
想知道在C++中是否存在一种方法可以复用这种“闭包生成器”,优先采用无指针的实现方案。
内容的提问来源于stack exchange,提问作者miyou379
相关产品推荐
相关产品推荐

