这是代码,非常简单。
class Foo {
public:
void print() {
std::cout<<"Foo::print\n";
}
};
Game::Game() {
{
Foo foo;
player.onclick = bind(&Foo::print,foo);
}
player.onclick();
}
内部作用域完成后, foo 对象超出作用域,但仍调用 print 方法,我猜发生这种情况是因为player持有对 foo 对象的引用?有没有办法阻止这种情况发生?我不希望对象在应该被销毁的时候保持活动状态并接收事件。
谢谢。
您已绑定
foo
的副本;该副本的持续时间与绑定的函数对象一样长,而原始的 foo
在其作用域结束时被销毁。
如果不想让它保持活动状态,则绑定到指针(
&foo
)或引用(std::ref(foo)
);然后你必须小心,一旦 foo
超出范围,不要调用函数对象。请注意,无法从函数对象得知这已经发生了;调用它会产生未定义的行为。
为了在对象被销毁时安全地断开连接,您必须安排其析构函数重新分配
onclick
,或者让其他对象负责首先重新分配onclick
,然后销毁该对象。
我认为当您将
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();
}