如何保证对象';的寿命是否与成员函数的持续时间匹配? 我一直在使用回调来减少一些C++类之间的耦合。定义术语:我将调用回调的类称为调用者,接收回调的类称为被调用者。通常(但不一定),被调用方将拥有调用方。根据设计,调用者不知道被调用者

如何保证对象';的寿命是否与成员函数的持续时间匹配? 我一直在使用回调来减少一些C++类之间的耦合。定义术语:我将调用回调的类称为调用者,接收回调的类称为被调用者。通常(但不一定),被调用方将拥有调用方。根据设计,调用者不知道被调用者,c++,lifetime,C++,Lifetime,我遇到了一个与调用者对象的生命周期有关的问题:它不能保证在进行任意回调后它仍然是活动的。就拿这个基本的例子来说: void caller::f() { /* Some work */ if (...) { /* [1] Execute callback */ _callee->callback(this); } /* [2] Some more work */ } 假设被调用方已经动态地分配了调用方,并且专门注册了回

我遇到了一个与调用者对象的生命周期有关的问题:它不能保证在进行任意回调后它仍然是活动的。就拿这个基本的例子来说:

void caller::f()
{
    /* Some work */
    if (...)
    {
        /* [1] Execute callback */
        _callee->callback(this);
    }
    /* [2] Some more work */
}

假设被调用方已经动态地分配了调用方,并且专门注册了回调以等待某个条件发生。当它这样做时,被调用方将从[1]处的回调中删除调用方。如果是这种情况,那么控件将返回到caller::f,但是
将被删除,[2]处的任何代码都很可能崩溃

在一般情况下,调用者不能对被调用者做出任何假设。它不知道被调用方是否拥有
this
,或者是否可能解除分配
this
,因此我需要一些常规方法来防止取消分配调用方成员函数的范围

我相信一个可能的解决方案是围绕着
boost::shared\u ptrs
从这个
启用共享,尽管我从未使用过它。由于这些回调在处理能力有限的移动设备上运行得非常频繁(每秒40多次以上),因此我还担心创建和分发许多
共享\u ptr
的开销


委托是一种非常常见的Objtovi.C模式,我对普通C++设计模式不太熟悉。这个问题有没有快速简便的解决方法?如果不是,那么这个设计通常是如何在C++中实现的?

< p>当被调用的代码>删除< /Cult>的调用方时,调用调用方的析构函数。您应该确保
f
已经完成

我猜
f
是一个线程,所以最简单的解决方案是:

线程:

running = true;
while (!must_exit)
    /* do something */
破坏器:

thread->must_exit = true;
while (thread->running)
    sleep(a_little);
/* continue with destruction */
如果
f
不是线程,那么同样的原理可以应用于
f
使其对象(并通过其析构函数)知道何时运行和何时不运行的情况


如果您不想使用析构函数方法,您仍然可以通过被调用方调用的函数来实现此功能,告诉
f
不要再次运行并等待它停止。然后被调用者继续删除调用者

比如说:

void caller::f()
{
    if (being_deleted)
        return;
    running = true;
    /* Some work */
    if (...)
    {
        /* [1] Execute callback */
        _callee->callback(this);
    }
    /* [2] Some more work */
    running = false;
}

void caller::make_f_stop()
{
    being_deleted = true;
    while (running)
        sleep(a_little);
}

当被调用方
delete
s调用方时,调用调用方的析构函数。您应该确保
f
已经完成

我猜
f
是一个线程,所以最简单的解决方案是:

线程:

running = true;
while (!must_exit)
    /* do something */
破坏器:

thread->must_exit = true;
while (thread->running)
    sleep(a_little);
/* continue with destruction */
如果
f
不是线程,那么同样的原理可以应用于
f
使其对象(并通过其析构函数)知道何时运行和何时不运行的情况


如果您不想使用析构函数方法,您仍然可以通过被调用方调用的函数来实现此功能,告诉
f
不要再次运行并等待它停止。然后被调用者继续删除调用者

比如说:

void caller::f()
{
    if (being_deleted)
        return;
    running = true;
    /* Some work */
    if (...)
    {
        /* [1] Execute callback */
        _callee->callback(this);
    }
    /* [2] Some more work */
    running = false;
}

void caller::make_f_stop()
{
    being_deleted = true;
    while (running)
        sleep(a_little);
}

继续使用共享指针,但如果可能,请使用
std::shared_ptr
而不是
boost::shared_ptr
。它位于(当前)标准库中,因此无需添加不必要的boost依赖项。如果您已经在使用boost,那么也可以

你没有具体说明你在说什么类型的移动设备,但现代智能手机的处理器运行在数百或数千兆赫,甚至低功耗手机通常运行Java程序(带有垃圾收集)。共享指针基本上是引用计数的。这不是一项资源密集型活动


如果您的设备能够每秒实际运行回调超过40次,我怀疑它在共享指针方面会有任何问题。不要过早地优化执行速度。提前优化安全性和合理性。

继续使用共享指针,但如果可能,使用
std::shared_ptr
而不是
boost::shared_ptr
。它位于(当前)标准库中,因此无需添加不必要的boost依赖项。如果您已经在使用boost,那么也可以

你没有具体说明你在说什么类型的移动设备,但现代智能手机的处理器运行在数百或数千兆赫,甚至低功耗手机通常运行Java程序(带有垃圾收集)。共享指针基本上是引用计数的。这不是一项资源密集型活动


如果您的设备能够每秒实际运行回调超过40次,我怀疑它在共享指针方面会有任何问题。不要过早地优化执行速度。为安全性和合理性进行过早优化。

绕过无法执行的代码的通常方法是抛出异常。这应该由被调用者在删除调用者后通常返回调用者的位置完成。异常将在函数末尾的调用方代码中捕获

我不能说我喜欢这个解决方案,但我认为这是由于被调用方拥有调用方这一不寻常的情况造成的


我不知道智能指针会有什么帮助,因为没有人拥有指针的第二个副本。

绕过无法再执行的代码的通常方法是抛出异常。这应该由被调用者在删除调用者后通常返回调用者的位置完成。异常将在函数末尾的调用方代码中捕获

我不能说我喜欢这个解决方案,但我认为这是由于