可以说编译期执行是相当一部分编译优化的基础,这部分优化通常发生在优化的前期,主要是代码“语义”层面的优化。没有了这些优化,C++的一大原则:零代价抽象的“零代价”肯定要大打折扣。
甚至C++标准也在强力推广使用编译器在编译时完成计算的行为,比如C++11中提出,并在C++14中获得超强进化的constexpr关键字,简直就是明确要求编译器内要自带一个解释器。
举例子来说,大多数编译器都会帮你做常量的传播和消除,帮你做很多趟循环的分析,帮你做返回值优化,帮你干掉那些看起来没有任何用的代码等等。如此一来,充满了复杂而多层次的抽象的C++代码在编译过后就可以变成一些执行效率不亚于采用低层次抽象甚至没有抽象的C++代码的二进制结果,而开发效率上前者则要高得多。想看实际效果的话,在g++中采用-O0和-O3编译或者VS中Debug和Release编译配置下的巨大性能差异中相当一部分就是编译时计算带来的提升,尤其在抽象比较复杂,比如使用了大量STL时区别更为明显。
事实上,编译器可以做的绝大多数“语义”上的优化都是需要编译期计算的。这些优化的一大原则是保证程序运行对外界产生的影响和“预期”一致,“预期”的结果则是靠标准中规定的一系列well defined behavior组成的。如果编译器经过分析发现不论运行时输入什么样的信息,最终程序都不会对外界产生任何影响,那大可以把整个程序都优化成空。
上面提到了运行时信息,事实上这是编译优化的极限之一,也即最终所有操作都应该直接或间接地依赖到某个在运行时才能确定的信息,例如一次键盘输入,一幅摄像头采集到的图像等。
当然现在也不是已经做到完美了,仍有很多相关的研究在进行。例如编译期计算仍然只能发生在一个translation unit之内,跨translation unit的优化目前还在快速发展之中
not about