在很長一段時間以來,我們一直有這樣的工作很多這樣的記錄系統:檢測在printf函數()調用的參數
#define LOG(LEVEL, FORMAT, ...) my_log_function(LEVEL, __FUNCTION__, \
__LINE__, FORMAT, __VA_ARGS__)
my_log_function
將檢查日誌記錄的級別目前到位,如果可以的話,會做一些漂亮的打印(文件/行,它記錄的日期,時間等)。
現在的問題是,這個宏定義有兩個巨大的缺點:
/使用時,在微距傳輸的參數評估,這意味着大量的性能命中時,你的代碼是擁擠通過LOG()調用。
見這裏的例子:
LOG(INFO, "The parameters: %s %d %d\n", heavyMethod().name(),
heavyMethod2().id(), work_done_in_this_function());
即使「INFO」日誌記錄級別被禁用,所有參數都將進入該功能前進行評估。
如果您登錄函數調用,你會看到這樣的情況:
- 調用
heavyMethod()
- 調用
name()
- 調用
heavyMethod2()
- 調用
id()
- 調用
work_done_in_this_function()
- (最後)致電
my_log_function()
當你有1000個LOG()調用時,這很糟糕。
解決方法很簡單:拿出的my_log_function
,檢查水平的代碼並修改這樣的LOG()的定義:
#define LOG(LVL, FMT, ...) do{ if(level_enabled(LVL)) \
{ \
my_log_function(LVL, ...); \
} \
}while(0)
這可以確保當日志級別是不足夠的,參數沒有評估(因爲它們在括號內)。
/正如你在我的例子中看到的那樣,被調用的最後一個函數正在做某種工作,如果沒有調用LOG()函數就不會完成這些工作。
這在我們的代碼中發生了很多(我知道,這個SUCKS HARD,人們已經失去了手指)。
隨着我在點 /中所作的增強,我們現在必須檢查每個LOG()調用,以查看是否已完成一些未做的工作,現在我們中止了調用。
這是你們輸入的地方:你知道一個簡單的方法來檢查一個函數的參數是否實際上正在修改某些東西嗎?
該項目是在C++中,大多數「不會修改任何東西」的函數被標記爲const。
注意它包括像一些技巧:LOG(INFO, "Number of items: %d\n", _item_number++);
,其中_item_number
是一個對象的類的成員(因此如果INFO級未激活:-(沒有得到遞增)
TL; DR: 。永遠,永遠做工作的printf()始終做到這一點,事前:
// BAD
printf("Number: %d\n",++i);
// GOOD
i++;
printf("Number: %d\n", i);
'#define'宏是[evil](http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5) –
@Als:高亮顯示它:) – Gui13
printf( 「Number:%d \ n」,++ i); –