c ++ std :: bind保持对象活着

时间:2012-04-04 19:54:18

标签: c++ c++11

这是代码,非常简单。

class Foo
{
public:
    void print()
    {
        std::cout<<"Foo::print\n";
    }
}; 


Game::Game()
{
    {
        Foo foo;
        player.onclick = bind(&Foo::print,foo);

    }
    player.onclick();
}

在内部作用域完成后,foo对象超出了作用域,但仍然调用了print方法,我想这是因为播放器持有对foo对象的引用?有没有办法阻止这种情况发生?我不希望对象保持活着,并且当它们被销毁时会收到事件。

感谢。

3 个答案:

答案 0 :(得分:4)

您绑定了foo的副本;该副本持续与绑定的函数对象一样长,而原始foo在其作用域的末尾被销毁。

如果你不想让它保持活着,那么绑定到指针(&foo)或引用(std::ref(foo));然后,一旦foo超出范围,您必须小心不要调用函数对象。请注意,无法从函数对象中判断出这种情况已经发生;调用它会产生不确定的行为。

为了在对象被销毁时安全地断开连接,你必须安排它的析构函数重新分配onclick,或者让其他一些对象负责首先重新分配onclick,然后摧毁它对象

答案 1 :(得分:0)

从你的描述中听起来你真的想要一个事件循环。虽然std::bind对于类似的东西很有用,但它本身并不是唯一的。我建议你看一下boost.signals

答案 2 :(得分:0)

我认为您将shared_ptr分配给Foo时应使用Player,并在weak_ptr中将Foo保留到Player。然后尝试锁定weak_ptr函数中的onclick以查看Foo是否仍然有效。像这样:

using namespace std;
class Foo
{
    public:
        void print()
        {
            cout<<"Foo::print\n";
        }
}; 

class Player
{
    public:
        weak_ptr<function<void()>> _onClickFuntion;
        void onclick()
        {
            shared_ptr<function<void()>> tempFunction(_onClickFunction.lock());
            if (tempFunction)
                tempFunction();
        }
}

Game::Game()
{
    {
        Foo foo;
        player._onClickFuntion = shared_ptr<function<void()>>(new bind(&Foo::print,foo));
    }
    player.onclick();
}