管理由 std::bind 绑定的成员函数的生命周期
Managing the lifetime of member functions bound by `std::bind`
我目前正在尝试用 C++11 编写事件队列。我正在使用 std::bind
获取 std::function
对象,这些对象在某些事件发生时被调用。代码大致如下所示:
class A
{
public:
void handle();
};
class B { ... };
// Later on, somewhere else...
std::vector< std::function< void() > functions;
A a;
B b;
functions.push_back( std::bind( &A::handle, &a ) );
functions.push_back( std::bind( &B::handle, &b ) );
// Even later:
for( auto&& f : functions )
f(); // <--- How do I know whether f is still "valid"?
有什么方法可以保证函数对象的有效性,这样我就可以避免在这里被未定义的行为绊倒吗?
我已经在这里查看了这个问题,,但它只讨论了删除指向绑定对象的指针是否会引发未定义的行为。我更感兴趣的是如何处理这样一个对象的销毁。有什么方法可以检测到吗?
编辑:澄清一下,我知道我不能保证非静态、非全局对象的生命周期。通知它们销毁就足够了,这样就可以删除无效的函数对象。
正如@Joachim 所说,没有生命周期与成员函数关联(它是代码部分,而不是数据)。所以你问是否有办法在执行回调调用之前知道对象是否仍然存在。
你必须建立一种框架,其中对象控制器在它被销毁时通知容器,这样容器就可以从它的 "observers" 中删除它,向量包含所有对象。为此,对象必须在其实例中记住容器的指针。
更新
@Jason 说说shared_ptr的使用。可以使用它们,但在这种情况下,不解决如何销毁其他对象通知列表中的对象 linked 的情况。 Shared_ptr 推迟销毁一个实例,直到所有 "managed" 对它的引用都被删除。但是,如果您需要销毁对象 A,并删除对它的所有引用,因为必须删除该对象,您必须查看所有存储 shared_ptr 的容器并将其删除。很痛苦activity。最简单的解决方案(使用原始 ptr 或 shared_ptr,如果你可以使用它们,则无关紧要)是观察者和被观察者之间的两个 link 连接,这样每个人都可以通知其销毁到另一个。如何存储这些信息?实现它的许多方法:哈希表、观察者中的插槽等
实现预期结果的一个 hack/workaround 是使用 std::shared_ptr 类型的参数。当绑定被破坏时,共享指针也被破坏——当它是最后一个引用时,它会做正确的事情。但是,这涉及对所用签名的更改。为了让它稍微不那么尴尬,你可以使用接受 std::shared_ptr this 的静态方法——有点像 python 中的 self 参数概念,如果你熟悉的话。
或者,如果您对 C++11 没问题,您可以只使用共享指针的 lambda 捕获。
您需要动态分配实例才能使用此方法。
我目前正在尝试用 C++11 编写事件队列。我正在使用 std::bind
获取 std::function
对象,这些对象在某些事件发生时被调用。代码大致如下所示:
class A
{
public:
void handle();
};
class B { ... };
// Later on, somewhere else...
std::vector< std::function< void() > functions;
A a;
B b;
functions.push_back( std::bind( &A::handle, &a ) );
functions.push_back( std::bind( &B::handle, &b ) );
// Even later:
for( auto&& f : functions )
f(); // <--- How do I know whether f is still "valid"?
有什么方法可以保证函数对象的有效性,这样我就可以避免在这里被未定义的行为绊倒吗?
我已经在这里查看了这个问题,
编辑:澄清一下,我知道我不能保证非静态、非全局对象的生命周期。通知它们销毁就足够了,这样就可以删除无效的函数对象。
正如@Joachim 所说,没有生命周期与成员函数关联(它是代码部分,而不是数据)。所以你问是否有办法在执行回调调用之前知道对象是否仍然存在。
你必须建立一种框架,其中对象控制器在它被销毁时通知容器,这样容器就可以从它的 "observers" 中删除它,向量包含所有对象。为此,对象必须在其实例中记住容器的指针。
更新
@Jason 说说shared_ptr的使用。可以使用它们,但在这种情况下,不解决如何销毁其他对象通知列表中的对象 linked 的情况。 Shared_ptr 推迟销毁一个实例,直到所有 "managed" 对它的引用都被删除。但是,如果您需要销毁对象 A,并删除对它的所有引用,因为必须删除该对象,您必须查看所有存储 shared_ptr 的容器并将其删除。很痛苦activity。最简单的解决方案(使用原始 ptr 或 shared_ptr,如果你可以使用它们,则无关紧要)是观察者和被观察者之间的两个 link 连接,这样每个人都可以通知其销毁到另一个。如何存储这些信息?实现它的许多方法:哈希表、观察者中的插槽等
实现预期结果的一个 hack/workaround 是使用 std::shared_ptr 类型的参数。当绑定被破坏时,共享指针也被破坏——当它是最后一个引用时,它会做正确的事情。但是,这涉及对所用签名的更改。为了让它稍微不那么尴尬,你可以使用接受 std::shared_ptr this 的静态方法——有点像 python 中的 self 参数概念,如果你熟悉的话。
或者,如果您对 C++11 没问题,您可以只使用共享指针的 lambda 捕获。
您需要动态分配实例才能使用此方法。