简体   繁体   English

C ++捕获对布尔错误值的引用

[英]c++ captured reference to bool wrong value

I capture local bool value by reference to lambda and the first time it gets captured the value is unassigned (some random value). 我通过引用lambda捕获本地布尔值,并且在第一次捕获该值时未分配该值(某些随机值)。 Why? 为什么?

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;
            }
        });

There's not quite enough context in the provided code to be certain, but as sharth hinted in the comments, the problem is almost certainly that singleConfirmed is an automatic, local variable that has gone out of scope (been destroyed) by the time the lambda is invoked, which means the lambda will be working with a wild reference. 提供的代码中没有足够的上下文可以确定,但是正如注释中的sharth所暗示的那样,问题几乎可以肯定, singleConfirmed是一个自动的局部变量,到lambda被删除时,它已经超出范围(被销毁)。被调用,这意味着lambda将使用野生引用。 To solve this, you need to use something that won't be destroyed when the scope exits. 为了解决这个问题,您需要使用在范围退出时不会被破坏的东西。 That means dynamic allocation. 这意味着动态分配。 Dynamic allocation means you'll need to deallocate when the lambda is destroyed. 动态分配意味着您需要在销毁lambda时取消分配。 The simplest way to ensure that is to use a smart pointer. 确保这一点的最简单方法是使用智能指针。 Putting that all together, my suggestion is to store the bool in a shared_ptr and capture it by value: 综上所述,我的建议是将bool存储在shared_ptr并按值捕获它:

auto singleConfirmed = std::make_shared<bool>(false);
button->addTouchEventListener([text, singleConfirmed](Ref*, Widget::TouchEventType type)
{
   // ...
}

( text appears to be some sort of pointer that you're capturing by value, so that should be ok as long as it doesn't get delete d before the lambda goes away) text似乎是您按值捕获的某种指针,因此只要在lambda消失之前不delete ,就可以了)

As swarth's and dlf's comment suggest, the lambda is almost certainly being run outside the scope of the local variable singleConfirmed . 正如swarth和dlf的评论所暗示的那样,lambda几乎可以肯定在局部变量singleConfirmed的范围之外运行。 The name of addTouchEventListener strongly suggests that the function object will be stored and executed in response to some user event later, and not executed now synchronously. addTouchEventListener的名称强烈建议功能对象将在以后响应某些用户事件而存储和执行,并且现在不同步执行。

When a lambda is going to be executed out of the scope in which it was created, it doesn't make sense to capture variables by reference, because those variables are going to be out of scope by the time it's executed, and therefore, using the reference is invalid. 当要在创建Lambda的范围之外执行Lambda时,通过引用捕获变量是没有意义的,因为在执行时这些变量将超出范围,因此,使用该引用无效。

Instead, you should capture by value. 相反,您应该按价值来捕获。 However, by default, value-captured variables are const , so you cannot assign to it inside the lambda, as it seems you want to do here. 但是,默认情况下,值捕获的变量是const ,因此您无法在lambda中将其赋值,就像您想要在此处执行的那样。 You need to declare the lambda mutable to make the value-captured variables non- const : 您需要声明lambda mutable以使值捕获变量变为非const

bool singleConfirmed = false;
button->addTouchEventListener(
    [text, singleConfirmed](Ref*, Widget::TouchEventType type) mutable {
        // everything in here stays the same
    })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM