简体   繁体   中英

c++ std::bind keeping object alive

Here is the code, it's pretty straightforward.

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


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

    }
    player.onclick();
}

After the inner scope is done the foo object goes out of scope, but the print method is still called, I guess this happens because player holds a reference to the foo object? Is there a way to stop this from happening? I don't want objects to stay alive and receive events when they are supposed to be destroyed.

Thanks.

You are binding to a copy of foo ; that copy lasts as long as the bound function object, while the original foo is destroyed at the end of its scope.

If you don't want to keep it alive, then bind to a pointer ( &foo ) or a reference ( std::ref(foo) ); and then you must be careful not to call the function object once foo has gone out of scope. Note that there's no way to tell from the function object that this has happened; calling it will give undefined behaviour.

In order to safely disconnect the object when it's destroyed, you would have to either arrange for its destructor to reassign onclick , or make some other object responsible for first reassigning onclick , and then destroying the object.

From your description it sounds like you actually want an event loop. While std::bind is useful for something like that it isn't one all by itself. I suggest you have a look at boost.signals

I think you should use shared_ptr when you assign Foo to Player , and keep a weak_ptr to Foo in Player . Then try to lock the weak_ptr in the onclick function to see if Foo is still alive. Something like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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