2010年7月7日 星期三

[C++ 程式設計]加速編譯方法 - 相依性問題

降低程式相依性

儘可能減少在 header 檔中 include 多餘的 header 檔。因為這樣會提升物件之間的相依性,當我們更動 header 檔 A.h 時,編譯器會找出所有 include "A.h" 的 header 檔,會將他們也當做更動過的檔案,所有更動過的檔案都必須重新被編譯。因此沒有妥善規劃好標頭檔的相依性,將會導致許多的程式都需要被重新編譯,這將會浪費更多的編譯時間。

 
// A.h
 class A
 {...};

 // A.cpp
 #include "A.h"
 ...

 // B.h
 #include "A.h"
 class B
 {
     A* mpA;
     ...
 };

 // B.cpp
 #include "B.h"
 ...

 // C.h
 #include "B.h"
 class C
 {
     B* mpB;
     ....
 };
 
 // C.cpp
 #include "C.h"...

以上述程式碼為例,當我們更動 A.h 時,會使編譯器重新編譯 A.cpp 、 B.cpp 與 C.cpp ,因為 A.h 間接的被所有檔案所 include 。以下為修改過後的程式碼:

 // B.h
 class A;
 class B
 {
     A* mpA;
     ...
 };

 // B.cpp
 #include "A.h"
 #include "B.h"
 ...

 // C.h
 class B;
 class C
 {
     B* mpB;
     ....
 }

 // C.cpp
 #include "B.h"
 #include "C.h"
 ...

這方法稱為 predeclaration ,讓你在定義 class 時告訴編譯器,其中的 data members 是某 class 的指標,可以先略過其實作。因此當更動 A.h 時,只有 A.cpp 與 B.cpp 需要被重新編譯。

但並非所有的狀況都可使用 predeclaration ,只要必須在編譯時期就需要知道 class 所佔的記憶體大時,class 就一定須先被定義。例如繼承或包含實體物件,以下為範例:
 
 // B.h
 #include "A.h"
 class B : public A    // inheritance
 {
     ...
 }
 

 // C.h
 #include "A.h"
 class C
 {
     A mA;    // instance
     ...
 }

儘可能將 function 於 cpp 檔內實作,除非有特殊需求,如 inline 與效能優化。

2 則留言:

  1. C++的template也有可能大幅度的增加compile時間,如果只是一些stl generic container可能還好,但是現在有一些像是炫技的template meta programming,不但一般凡人無法理解程式碼,compile時間和dependency也會大幅提高,只是有時候用上癮了也不得不用...boost...

    回覆刪除
  2. 對歐, template 都沒提到。不過我想這個部分比較適合你撰寫,在 metaprogramming 下打滾了這麼久了...因該有很多體悟。

    回覆刪除