[英]How to make sure a function is only called once
假設我有一個名為caller的函數,它將調用一個名為callee的函數:
void caller()
{
callee();
}
現在可以在應用程序中多次調用調用者,並且您希望確保只調用一次調用者。 (一種懶惰的初始化),你可以使用一個標志來實現它:
void caller()
{
static bool bFirst = true;
if(bFirst)
{
callee();
bFirst = false;
}
}
我的意見是它需要更多的代碼,並且每次調用函數調用者都需要再檢查一次。
對我來說更好的解決方案如下:(假設被調用者返回int)
void caller()
{
static int ret = callee();
}
但如果callee返回void,則無法處理此情況,我的解決方案是使用逗號表達式:
void caller()
{
static int ret = (callee(), 1);
}
但問題在於,逗號表達式並不常用,人們在看到這行代碼時可能會感到困惑,從而導致維護問題。
你有什么好主意確保只調用一次函數嗎?
你可以用這個:
void caller()
{
static class Once { public: Once(){callee();}} Once_;
}
線程安全:
static boost::once_flag flag = BOOST_ONCE_INIT;
boost::call_once([]{callee();}, flag);
您可以通過函數指針隱藏該函數。
static void real_function()
{
//do stuff
function = noop_function;
}
static void noop_function()
{
}
int (*function)(void) = real_function;
呼叫者只是調用將在第一次執行工作的function
,並且不會對任何后續呼叫執行任何操作。
你用布爾標志第一個變體bFirst
是什么都沒有說什么,編譯器會為你implictly在其他變體做一個顯式手動implementatuion。
換句話說,在您所提出的所有變體的典型實現中,將在生成的機器代碼中額外檢查布爾標志。 所有這些變體的性能都是相同的(如果這是您的關注)。 第一個版本中的額外代碼可能看起來不那么優雅,但這對我來說似乎並不重要。 (包裹它。)
無論如何,你所擁有的第一個變量基本上是如何正常完成的(直到你開始處理多線程等問題)
受到一些人的啟發,我認為使用宏來包裝逗號表達式也會使意圖明確:
#define CALL_ONCE(func) do {static bool dummy = (func, true);} while(0)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.