使用lambda / std :: function删除拥有函数

时间:2018-04-07 17:49:51

标签: c++ lambda

我有一个Layer类,其中包含某些对象,如按钮,滑块等。我已经构建了Layer类,以便它能够自我刷新。基本上,它删除所有/大多数对象,然后重新创建它们。原因是我有各种功能,如更改字体大小或我的UI的主题,我希望立即显示更改。

实现此目标的唯一方法是简单地重建所有内容,因为主题和字体大小会影响所有内容的外观和布局。这一切都很有效,我对系统感到满意。

但是,当属于该层的对象启动刷新时,会出现问题(以及我所说的崩溃问题)。例如,我有一个字体大小滑块,它应该改变字体大小然后刷新图层。它具有对层的刷新功能的回调,由lambda捕获,并存储在成员std :: function对象中。执行该函数时会发生的情况是,在某个时刻,在调用函数完成之前,滑块当然会被破坏并随之破坏该函数。因此,当前运行的功能停止存在并且程序崩溃。

我的问题是,通过这种自相矛盾的情况,实现这种不会导致崩溃的行为会是一种优雅而优雅的方式吗?

编辑:代码

class MySlider : public MyNode
{
    //... various other class members

    std::function<void()> functionOnRelease = nullptr;

    MySlider::MySlider(/*constructor arguments*/)
    {
        this->preferenceKey = key;

        slider->addTouchEventListener([=](Ref* sender, ui::Widget::TouchEventType type)
        {
            if (type == ui::Widget::TouchEventType::ENDED)
                on_release();
        });

        //... remainder of constructor body
    }

    void MySlider::set_function_on_release(const std::function<void()>& functionOnRelease)
    {
        this->functionOnRelease = functionOnRelease;
    }

    void on_release()
    {
        if (preferenceKey.empty() == false)
            PREFM->set_preference(preferenceKey, slider->getPercent() + min);

        if (functionOnRelease)
            functionOnRelease();

        //the program crashes at this point when the slider gets destroyed
    }
}


//The layer in question and the function that creates its slider
void Options::create_font_size_slider()
{
    NodeVector sliders;

    //there's a static create function convention imposed by the engine    
    auto fontSizeSlider = MySlider::createWithPreferenceAutomatic("Font Size: ", "FontSizePercentage", 50, 150, false, sliders);

    fontSizeSlider->set_function_on_release([=] { this->refresh(); /*this kills the slider*/});
}

编辑2:

我设法通过一个简单而丑陋的黑客来避免崩溃。在稍微延迟(0.05秒)后,我强制刷新()函数在单独的线程上发生。这为所有事情提供了足够的时间,而没有明显的延迟。我可以忍受在设备非常慢和线程调度奇怪的情况下偶然发生的崩溃,因为在崩溃发生之前需要完成的所有事情都要完成。

1 个答案:

答案 0 :(得分:0)

您可以通过引用计算对象来解决这个问题(例如COM)。基本上是:

保留()会破坏对象的引用计数。

Release()减少对象的引用计数,如果它现在为零,则删除它。

对象以引用计数1开始生命,并且您从不显式删除引用计数对象(保护析构函数)。

现在,当一个对象想要触发刷新时,它可以先调用自身保留。当控件返回到对象时,它可以调用Release,然后立即返回。对Release的调用可能会删除该对象,但只要它不随后触及其实例数据,这并不重要。

引用计数可以解决很多对象生命周期问题,您可以调用delete (this)。娱乐时间。另见:

http://en.cppreference.com/w/cpp/memory/shared_ptr