我正在使用一个可以在运行时启用/禁用报告的日志记录模块.电话通常类似于:
WARN( "Danger Will Robinson! There are " + boost::lexical_cast(minutes) + " minutes of oxygen left!" );
我正在使用WARN的内联函数,但我很好奇在幕后进行了多少优化 - 在整个程序中对参数的评估将是昂贵的.该WARN
函数基本是这样的:
bool WARNINGS_ENABLED = false; inline void WARN(const string &message) { if (!WARNINGS_ENABLED) { return; } // ... }
鉴于构造字符串参数没有副作用,编译器会优化它吗?要求(优化的一定水平-Ox
在g++
一段x
)?
如果您需要能够在运行时有选择地启用和禁用警告,则编译器将无法优化调用.
你需要的是将你的函数重命名为WARN2
并添加一个宏,如:
#define WARN(s) do {if (WARNINGS_ENABLED) WARN2(s);} while (false)
这将阻止在运行时评估s,除非您启用了警告.
do-while东西是一个技巧,允许它在代码中的任何地方使用(裸体语句,支撑if-block中的语句,unbraced if-block中的语句,braced和unbraced while语句等等).
您可以使用-S选项检查GCC/G ++的功能.这将在实际汇编之前输出代码 - 请参阅gcc(1).
在这种情况下,GCC和G ++或多或少的行为相同.所以我首先将代码翻译成C以进行进一步的测试:
char WARNINGS_ENABLED = 0; inline void WARN(const char* message) { if (!WARNINGS_ENABLED) { return; } puts(message); } int main() { WARN("foo"); return 0; }
运行gcc -O3 -S file.c并查看输出文件' file.s '
你会看到GCC 没有删除任何东西!
这不是你要求的,但为了给编译器提供优化代码的机会,你必须使WARNINGS_ENABLED 保持不变.另一种方法是使其静态,而不是更改该文件中的值.但是:使它静止会产生副作用,即符号不会被导出.
static const char WARNINGS_ENABLED = 0; inline void WARN(const char* message) { if (!WARNINGS_ENABLED) { return; } puts(message); } int main() { WARN("foo"); return 0; }
GCC然后完全清理代码.