我通过参考lambda来捕获本地bool值,并且当它第一次被捕获时,值是未赋值的(一些随机值)。为什么?
bool singleConfirmed=false;
button->addTouchEventListener([text, &singleConfirmed](Ref*, Widget::TouchEventType type)
{
if (type != Widget::TouchEventType::ENDED) return;
if (!singleConfirmed)
{
cocostudio::ActionManagerEx::getInstance()->playActionByName(R_tutorialDialog.c_str(), "MoveToTop");
text->setString(G_str("Tutorial_Single/Multiplayer"));
singleConfirmed=true;
return;
}
else
{
cocostudio::ActionManagerEx::getInstance()->playActionByName(R_tutorialDialog.c_str(), "SwipeToLeft");
text->setString(G_str("Tutorial_Single/Multiplayer"));
return;
}
});发布于 2014-08-01 18:50:57
正如斯沃斯和dlf的评论所表明的那样,lambda几乎肯定是在局部变量singleConfirmed的范围之外运行的。addTouchEventListener的名称强烈表示函数对象将在以后响应某个用户事件而被存储和执行,而不是现在同步执行。
当一个lambda要在其创建的作用域之外执行时,通过引用捕获变量是没有意义的,因为这些变量在执行时将超出作用域,因此使用该引用是无效的。
相反,您应该按值捕获。但是,默认情况下,捕获的值变量是const,因此不能在lambda中分配给它,就像您在这里想要做的那样。您需要声明lambda mutable以使值捕获的变量非const。
bool singleConfirmed = false;
button->addTouchEventListener(
[text, singleConfirmed](Ref*, Widget::TouchEventType type) mutable {
// everything in here stays the same
})发布于 2014-07-31 14:22:42
提供的代码中没有足够的上下文可以确定,但是正如sharth在注释中所暗示的那样,问题几乎可以肯定的是,singleConfirmed是一个自动的局部变量,在调用lambda时已经超出了作用域(已被销毁),这意味着lambda将使用野生引用。要解决这个问题,您需要使用一些在作用域退出时不会被破坏的内容。这意味着动态分配。动态分配意味着,当lambda被销毁时,您需要重新定位。确保这一点的最简单方法是使用智能指针。综上所述,我的建议是将bool存储在shared_ptr中并按值捕获它:
auto singleConfirmed = std::make_shared<bool>(false);
button->addTouchEventListener([text, singleConfirmed](Ref*, Widget::TouchEventType type)
{
// ...
}(text似乎是由值捕获的某种指针,所以只要在lambda离开之前没有得到deleted,就可以了)
https://stackoverflow.com/questions/25060263
复制相似问题