我目前正在尝试在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"?
有没有办法保证函数对象的有效性,以便我可以避免在这里遇到未定义的行为?
我已经在这里查看了这个问题std::function to member function of object and lifetime of object,但它只讨论了删除指向绑定对象的指针是否会引发未定义的行为。我对如何处理这样一个对象的破坏更感兴趣。有没有办法检测到这个?
编辑:为了澄清,我知道我无法保证非静态非全局对象的生命周期。通知它们的销毁是足够的,这样就可以删除无效的功能对象。
答案 0 :(得分:4)
正如@Joachim所说,没有生命周期与成员函数相关联(它是代码部分,而不是数据)。所以你要问在执行回调调用之前是否有办法知道对象是否仍然存在。
你要制作一种框架,其中对象dctor在销毁时通知容器,因此容器可以从包含所有对象的“观察者”中删除它。要做到这一点,对象必须在其实例中记住ptr到容器。
更新
@Jason谈到了shared_ptr的使用。可以使用它们,但在这种情况下,没有解决如何销毁在其他对象通知列表中链接的对象的情况。 Shared_ptr推迟了对实例的销毁,直到删除了对它的所有“托管”引用。但是如果你需要销毁对象A,并删除对它的所有引用,因为必须删除该对象,你必须查看存储shared_ptr的所有容器并将其删除。一个非常痛苦的活动。最简单的解决方案(使用原始ptr或shared_ptr,如果你可以使用它们,是无关紧要的)是观察者和被观察者之间的双链接连接,这样每个人都可以将其销毁通知给另一个。如何存储这些信息?许多方法来实现它:哈希表,观察者中的插槽等
答案 1 :(得分:0)
实现所需结果的一个hack / workaround将是使用std :: shared_ptr类型的参数。当绑定被破坏时,共享指针也是如此 - 当它是最后一个引用时它会做正确的事情。但是,这涉及对所用签名的更改。为了使它稍微不那么笨拙,你可以使用std :: shared_ptr这样的静态方法 - 有点像python中的self参数概念,如果你熟悉的话。
或者如果你对C ++ 11很好,你可以使用共享指针的lambda捕获。
您需要动态分配实例才能使用此方法。