如何保證某個函數只被調用一次 一個函數caller會在其內部調用另外一個函數callee,現在的情況是,caller可能會在多個地方被多次調用,而你希望callee只在第一次被調用時被調用一次。一般情況下,callee會是一個對環境或者資源的初始化工作。 或許,從代碼結構的角度來講,你第一個想到的是
一個函數caller會在其內部調用另外一個函數callee,現在的情況是,caller可能會在多個地方被多次調用,而你希望callee只在第一次被調用時被調用一次。一般情況下,callee會是一個對環境或者資源的初始化工作。
或許,從代碼結構的角度來講,你第一個想到的是把callee從caller中拿出來,放到某個合適的地方做初始化,這是個不錯的方法,但相信我,在有些時候這並不是個有效的辦法:你可能無法找個那個“合適的地方”,你也可能找到了但因此而失去lazy initialization的好處~~~。
這裡,我只想對這個問題找個好點的方法。
第一個方法很簡單,就是用個靜態的flag來判斷:
static bool flag = false; if(!flag) { callee(); flag = true; }這個可以非常完美的工作,但是代碼感覺多了點,不夠簡潔。
而且每個後續調用都要有個取反和判斷操作,這對調用頻繁的操作的性能是有影響的。另外,即使影響不大,從程式員感受的角度來看,你也不希望有多餘的判斷~~~
哦,取反可以去掉:
static bool flag = true; if(flag) { callee(); flag = false; }但是,判斷還是存在。
【編輯:SO上討論中有人指出,即使使用static變數,其實也會有一個判斷操作,這一點說出了問題的根本,所以關於效率的論述是不必要的】
當然,我們還有第二種更簡潔的方法,假設callee的返回類型時int:
static int dummy = callee(); // 1)完了,利用靜態變數只初始化一次的特點就可以實現,簡潔,而且高效。
但是,這裡有個問題:如果callee的返回類型時void,那怎麼辦?你不能:
static void dummy = callee(); static int dummy = (int)callee(); static int dummy = reinterpret_cast<int>(callee());因為void其實不是個類型,而是沒有類型。
即使你覺得自己很聰明,想出了下麵這種方式:
bool dummyfunc(void){return true;} static bool dummy = dummyfunc(callee());那也是不靈光的,不要以為callee返回void,把返回的void傳給dummyfunc的參數就可以了,因為void根本就不是個類型,根本沒有賦值,傳值這個概念~~~
幸虧C++中還有個叫逗號表達式的東西,說實話,C++用了7年多,這是我第一次發現逗號表達式這麼可愛:
逗號表達式會這個計算每個子表達式,並返回最後一個子表達式的值
於是,就有了這個解決方案:
static bool dummy = (callee(), true); // 2)也是同樣的簡潔、高效。
看來,直接用靜態變數初始化的方法是可以達到這個目的,而且會更好。
附:
我相信還會有其他方法來處理callee返回void的情況的,如果你知道,請不吝賜教!
來源:http://www.cnblogs.com/baiyanhuang/archive/2010/11/13/1876677.html