这是代码,非常简单。
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对象的引用?有没有办法阻止这种情况发生?我不希望对象保持活着,并且当它们被销毁时会收到事件。
感谢。
答案 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();
}