我正在尝试lambda
在项目中使用s,但我想我缺少有关闭包范围的信息。我测试了这段代码,以某种方式简化了我的问题。
#include <iostream>
#include <functional>
using namespace std;
void tester_wrapper(std::function<int(void)> cb, int counter){
if (counter == 10)
return;
else{
cout << cb() << endl;
tester_wrapper(cb, counter + 1);
}
}
void tester(std::function<int(void)> cb){
tester_wrapper(cb, 0);
}
int main()
{
auto getNum = ([](int starter) {
return [starter]() mutable {
return ++starter;
};
})(1);
tester(getNum);
tester(getNum);
}
首次调用tester
捕获的变量后,starter
将重置该输出,以便将相同的输出打印两次。
为了避免starter
lambda的内部counter()的这种行为,我该怎么办?本质上,第二个呼叫tester
必须打印从12开始的10个数字,而不是2。
编辑
感谢您的回答。我没有考虑过将副本传递给tester_wrapper
,所以找到了以下解决方案:
#include <iostream>
#include <functional>
using namespace std;
std::function<int(void)> mylambda(int starter){
return [starter]() mutable {
return ++starter;
};
}
void tester_wrapper(const std::function<int(void)>& cb, int counter){
if (counter == 10)
return;
else{
cout << cb() << endl;
tester_wrapper(cb, counter + 1);
}
}
void tester(const std::function<int(void)>& cb){
tester_wrapper(cb, 0);
}
int main()
{
/*auto getNum = ([](int starter) {
return [starter]() mutable {
return ++starter;
};
})(1);*/
auto getNum = mylambda(1);
tester(getNum);
tester(getNum);
}
但是,现在我不明白为什么旧getNum
的使用“外部”功能(即)输出相同的输出,而输出不同mylambda
。
(我应该为此发布一个新问题吗?)
变量不会重置,而是变量的不同副本。实际上,有一堆副本。第一个处于您创建的lambda的状态。第二个是在std::function
构造第一个时创建的。您必须记住,它将接收到的可调用对象复制到其自身中。因此,每次调用都会tester
启动一连串的副本。解决该问题的一种方法是将lambda传递到std::reference_wrapper
。
tester(std::ref(getNum));
tester(std::ref(getNum));
参考包装器将被复制,但是所有副本都将引用同一个lambda对象getNum
。
现在,假设您打算创建许多不同的对象(如)getNum
,std::function
并且提供的类型擦除是一种合理的操作方法,可以避免可能的代码膨胀。要记住的是不要创建多余的副本。因此,tester
按价值接受是合法的,但tester_wrapper
应改为按引用接受。这样一来,您只需在API边界的所需位置购买类型擦除即可。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句