使用预处理器切换代码非常常见:
#define MY_SWITCH (1)
#if MY_SWITCH
cout << "on" << Test(1);
#else
cout << "off" << Test(2);
#endif
但是,如果此代码段之外的代码发生更改(例如,如果重命名了Test()函数),则可能会发生禁用行因为未编译而仍然过时的情况。
我想使用不同类型的开关来执行此操作,以便在每个构建时编译代码,以便我可以立即找到过时的行。例如。像这样:
static const bool mySwitch = true;
if (mySwitch)
{
cout << "on" << Test(1);
}
else
{
cout << "off" << Test(2);
}
但是我需要阻止此方法消耗额外的资源。是否有任何保证(或可靠的假设)现代C ++编译器将删除非活动分支(例如使用优化)?
答案 0 :(得分:3)
几周前我遇到了这个问题 - 在我的代码库中禁用了一个有问题的诊断功能,发现替代代码中有一些新的错误阻止了编译。但是,我不会沿着你提出的路线前进。
你首先牺牲了使用宏的好处而不一定获得任何东西。我希望我的编译器能够优化死分支但是你不能依赖它和我觉得宏观方法使得更明显的是有两个不同的程序的“配置”,并且只能在特定构建中使用一个。
我会让你的持续集成系统(或任何驱动自动构建测试)循环遍历构建配置的各种组合(在命令行上使用-D
提供宏,可能来自Makefile或其他构建脚本,而不是在源代码中对它们进行硬编码)并对它们进行全部测试。
答案 1 :(得分:2)
您没有关于编译器优化的保证。 (如果您想要对C进行经过验证的优化,请查看compcert)。
但是,大多数编译器会在这种情况下进行优化,有些甚至可能会警告死代码。尝试启用优化的最新GCC或Clang/LLVM(例如g++ -Wall -Wextra -O2
)。
另外,我相信大多数编译器在生成的优化代码的执行时都不会消耗资源,但是它们会在编译时消耗资源。
也许使用constexpr
可能会帮助某些编译器更好地进行优化。
另外,查看生成的汇编代码(例如,使用g++ -O2 -fverbose-asm -S
)或编译器的中间转储(例如g++ -O2 -fdump-tree-all
,它提供数百个转储文件)。如果使用GCC,您可以使用MELT对其进行自定义,例如添加额外的编译时检查。