利用pre-compiled headers技术以加速编译速度 --以Borland C++ Builder为例 (四)
本文作者:王森 台湾交通大学科技管理研究所 [email protected]
<编译器指令#pragma hdrstop之前只能放系统标头文件吗?>
请大家回头看看在这之前所有被我们用来测试的程序原始文件。拿程序代码5来说,大家会发现,Unit2.cpp并没有放在编译器指令#pragma hdrstop之前,那幺是否代表笔者默认Unit2.cpp不能放在编译器指令#pragma hdrstop之前呢? 让我们来做个Project实验组,程序代码如下:
程序代码6-1: Unit1.cpp #include <iostream.h> #include <stdio.h> #include <vcl.h> #include "Unit2.h" #pragma hdrstop
#pragma argsused int main(int argc, char* argv[]) { cout << "Hello World" ; return 0; }
Unit2.h #ifndef Unit2H #define Unit2H
void test(void) ; #endif
Unit2.cpp #include <iostream.h> #include <stdio.h> #include <vcl.h> #include "Unit2.h" #pragma hdrstop
void test(void) { printf("test") ; }
然后我们试着编译看看。接着我们一个档案都不要删除,直接把Unit2.h与Unit2.cpp叫出来,把档案内容改成: 程序代码6-2: Unit2.h #ifndef Unit2H #define Unit2H
void test(void) ; void test1(void) ; #endif
Unit2.cpp #include <iostream.h> #include <stdio.h> #include <vcl.h> #include "Unit2.h" #pragma hdrstop
void test(void) { printf("test") ; } void test1(void) { printf("test1") ; } 再重新使用make编译。
同理,我们也做一组完全相同的Project当作对照组,档案内容几乎完全相同,除了我们把#include "Unit2.h"放回编译器指令#pragma hdrstop之后,我们也做跟上面实验组Project相同的测试:
程序代码7-1: Unit1.cpp #include <iostream.h> #include <stdio.h> #include <vcl.h> #pragma hdrstop #include "Unit2.h" #pragma argsused int main(int argc, char* argv[]) { cout << "Hello World" ; return 0; }
Unit2.h #ifndef Unit2H #define Unit2H
void test(void) ; #endif
Unit2.cpp #include <iostream.h> #include <stdio.h> #include <vcl.h> #pragma hdrstop #include "Unit2.h" void test(void) { printf("test") ; }
程序代码7-2: Unit2.h #ifndef Unit2H #define Unit2H
void test(void) ; void test1(void) ; #endif
Unit2.cpp #include <iostream.h> #include <stdio.h> #include <vcl.h> #pragma hdrstop #include "Unit2.h" void test(void) { printf("test") ; } void test1(void) { printf("test1") ; }
我们把这两次测试的结果列在下表 测试结果8:
Unit2.h在#pragma hdrstop之前 |
Unit2.h在#pragma hdrstop之后 |
编译次数 |
编译行数 |
编译时间 |
编译次数 |
编译行数 |
编译时间 |
第一次(build)程序代码6-1 |
202245 |
8.29 |
第一次(build)程序代码7-1 |
202258 |
8.65 |
第二次(make)程序代码6-1 |
0 |
0.14 |
第二次(make)程序代码7-1 |
0 |
0.16 |
第三次(make)程序代码6-2 |
202253 |
9.16 |
第三次(make)程序代码7-2 |
65 |
1.68 |
这个测试结果代表了什幺涵义呢?
-
这个测试结果并非只有系统标头文件才能放在编译器指令#pragma hdrstop之前,程序设计师自己定义的标头档也可以。
-
在标头档小小的更动会造成整个程序原始文件从头到尾重新编译,也使得编译器重新产生新的cache檔(注意:编译器会覆盖具有相同预先编译标记的vcl50.#??档,而非重新产生。其实这样也无可厚非,否则Lib目录下就会有好多具有相同预先编译标记的cache文件,这样可就糟糕了!)
在程序开发初期,程序标头文件常常会被修改,可是系统标头文件却几乎没有人会去动到他们,所以在整个系统的函式接口或数据结构尚未稳定之前,尽量先不要把程序设计师自己定义的标头文件放到编译器指令#pragma hdrstop之前。因为这幺一来,非但没有加速程序的编译速度,反而因为预先编译标记没有改变,可是标头档内容却变了,而迫使编译器每次都要重新编译这些标头档并产生新的cache檔(而且还要先删掉原先具有相同预先编译标记的cache文件,使得整体编译时间更长)。这个问题在我们的测试程序里并不明显,可是读者可以想象,如果今天我们是撰写GUI程序,我们常常要修改Form上的组件和事件处理函式,每次一修改,势必动到标头档(因为增添/删除组件,或是新增事件处理函式的时候都会让该Unit对应的标头档改变),如果我们的Project里头有好多Form,那事情可就不妙了!! 所以在此笔者的建议是:在程序设计初期,请先将这些程序设计师自行定义的标头文件移到编译器指令#pragma hdrstop之后(IDE所帮我们产生的Unit就是以此为预设情况),等到整个系统之中所有类别、函式接口、数据结构都大致底定的时候,再将这些标头文件移到编译器指令#pragma hdrstop之前,这样效果就会好很多。 
|