[英]How can I guarantee an object's lifespan matches the duration of a member function?
我一直在使用回調來減少某些C ++類之間的耦合。 定義術語:我將調用回調的類稱為調用者,將接收回調的類稱為被調用者。 通常(但不是必須),被呼叫者將擁有呼叫者。 通過設計,呼叫者不了解被呼叫者。
我遇到了一個與調用者對象的生命周期有關的問題:它不能保證在進行任何任意回調后它仍然會存在。 舉個基本的例子:
void caller::f()
{
/* Some work */
if (...)
{
/* [1] Execute callback */
_callee->callback(this);
}
/* [2] Some more work */
}
假設被呼叫者已經動態分配了呼叫者,並已專門為回調注冊以等待特定條件的發生。 完成后,被叫方將從[1]的回調中刪除該呼叫者。 如果是這樣的情況下,控制可能會返回主調::女,但this
已經被刪除了,並且在任何代碼[2]將很可能崩潰。
在一般情況下,呼叫者無法承擔有關被呼叫者的任何事情。 它不知道被調用方是否擁有this
,或者它是否可能取消分配this
,因此我將需要一些常規方法來防止在調用方成員函數的作用域內重新分配。
我相信可能的解決方案圍繞boost::shared_ptrs
和enable_shared_from_this
,盡管我從未使用過。 由於這些回調在處理能力有限的移動設備上非常頻繁地運行(每秒40次以上),因此我也擔心創建和shared_ptrs
許多shared_ptrs
的開銷。
委派是Objective-C中非常常見的模式。 我對常見的C ++設計模式不太熟悉。 是否有解決此問題的簡便方法? 如果沒有,通常如何在C ++中完成這種設計?
當被調用方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次,那么我懷疑共享指針是否會帶來麻煩。 不要過早地優化執行速度。 請過早優化安全性和衛生性。
繞過不再執行的代碼的通常方法是引發異常。 被呼叫者應在刪除呼叫者之后通常返回到呼叫者的位置進行此操作。 該函數的末尾將在調用者代碼中捕獲該異常。
我不能說我喜歡這種解決方案,但我認為這是由於被呼叫者擁有呼叫者的情況異常。
我不知道智能指針將如何提供幫助,因為沒有人擁有指針的第二個副本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.