C++ 管理由'std::bind'绑定的成员函数的生存期`

C++ 管理由'std::bind'绑定的成员函数的生存期`,c++,c++11,stdbind,C++,C++11,Stdbind,我目前正在尝试用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

我目前正在尝试用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"?
A类
{
公众:
无效句柄();
};
B类{…};
//后来,在别的地方。。。
std::vector函数;
A A;
B B;
functions.push_back(std::bind(&A::handle,&A));
functions.push_back(std::bind(&B::handle,&B));
//甚至后来:
用于(自动和f:功能)

f();// 正如@Joachim所说,成员函数没有生命周期(它是一个代码段,而不是数据)。因此,您询问是否有方法在执行回调调用之前知道对象是否仍然存在

你必须建立一种框架,当对象被销毁时,对象可以在其中保存或通知容器,这样容器就可以从它的“观察者”(包含所有对象的向量)中删除它。为此,对象必须在其实例中记住容器的ptr

更新


@Jason谈到了共享ptr的使用。可以使用它们,但在本例中,它并没有解决如何销毁其他对象通知列表中链接的对象的问题。Shared_ptr推迟销毁实例,直到删除对实例的所有“托管”引用。但是,如果您需要销毁对象A并删除对它的所有引用,因为必须删除该对象,那么您必须查看存储共享\u ptr的所有容器并将其删除。非常痛苦的活动。最简单的解决方案(使用原始ptr或共享ptr,如果可以使用的话,是不相关的)是观察者和被观察者之间的双链路连接,这样每个人都可以通知对方它的破坏。如何存储这些信息?实现它的方法有很多:哈希表、observer中的插槽等。实现所需结果的一种方法是使用std::shared_ptr类型的参数。当绑定被破坏时,共享指针也会被破坏——当它是最后一个引用时,它会做正确的事情。但是,这涉及对所用签名的更改。为了让它稍微不那么尴尬,如果您熟悉的话,可以使用静态方法,这些方法采用std::shared_ptr,有点像python中的自参数概念

或者,如果您对C++11没有问题,您可以只使用共享指针的lambda捕获


您需要动态分配实例以使用此方法。

成员函数没有“生存期”,另一方面,绑定成员函数时使用的对象确实有生存期,您必须考虑的是对象的生存期。不幸的是,没有办法保证非静态和非全局对象的生存期。是的,你是对的。是否可以通知非静态、非全局对象的销毁?或者我应该依靠各自的类实例来处理函数对象在删除时的删除吗?问题不是这样的:如果您放置了一个共享的\u ptr,那么您没有处理对象被销毁的情况;对象未被销毁,“可观察”仍会发出通知。您必须手动迭代并删除对删除对象的所有引用,这是非常不实际的。您能解释一下lambda捕获吗?我不知道你这是什么意思。@Mouze-对于这些类型的对象,你必须一路共享。存在有效的共享\u ptr实例时,无法销毁该对象。在本例中,当函数列表删除带有std::bind结果的std::函数,并且不存在其他共享的\u ptr时,该对象才会被删除。@Gnosophilon:在lambda方法中,您必须仍然使用共享的\u ptr,但它使您不必使用以“this”为参数的方法:
[shared\u this](){shared_this->handle();}
还注意std::enable_shared_from_this@Mouzeop的问题暂时改变了一点。原来的(仍然有效)我读到的问题是确保回调始终可以使用有效的对象执行,而shared_ptr解决了这个问题,因为函数对象的容器现在使这些对象保持活动状态。管理注册回调的容器是一个不同的问题,可以通过多种方式解决,例如从链表ret中获取票证迭代器关于“注册”的讨论.Boost.Asio经常用一个非常类似的问题演示共享模式,在他们的异步教程中达到顶峰。谢谢你的回答。我现在将使用一个辅助对象来管理连接。我只是认为讨论潜在的替代方案是值得的,因为我觉得我的解决方案不是很优雅。