2010年8月20日 星期五

Inline function、Marco

function 這種東西很好用,但呼叫 function 時都是有成本的,例如


int main()
{
  int nPreLoginTime = GetPreLoginTime();
  return TRUE;
}


程式流程會跑去 function 所在的記憶體位置執行,執行完再跑回來,這來來回回都是時間,雖然很短,但還是要盡量使用 inline

方法很簡單,就是在 function 原型前面加上 inline 即可,如此前置處理器就會幫你將函式主體 copy 到呼叫函式的地方,例如


main()
{
  double dblNumber = square(dblParam);
}

inline double square(double x)
{
  return x*x;
}


經過前置處理後會變


main()
{
  double dblNumber = dblParam * dblParam;
}


但也不是加了就有用,必須有辦法被合併,必須符合 inline function 的條件才能被合併,所以不必傻傻的連那種超長的 function 也加上 inline 修飾,遞迴就更不用說了。

另外在製作類別時,往往在 .h 檔中只會放 member function 原型,在 .cpp 中才實作內容,有時在 .h 中就會實作內容,例如


class T
{
  int m_nID;
  GetTID() {return T.m_nID};
};


這種寫在 .h 檔中的 function 也會被自動視為 inline function

Macro 通常用 #define 來製作,例如

#define max(a,b) (a > b)? a: b


inline 和 marco 一樣都會被複製到呼叫處,但 marco 因為是直接用取代貼上,所以有些地方需注意,marco 不執行參數型別檢查、也沒有語法檢查,也可能產生邏輯錯誤,例如以下指令都編得過,但會出問題


max(5, "Ascii");

(a > b)? max(i, j): t;
// 前置處理後變成
(a > b)? (i > j)? i: j: t

max(a++, a);
// 前置處理後變成
(a++>a)? a++: a;


所以 inline 應多使用,盡量少使用 marco,或是使用 marco 時加上括號,或 marco 設計時多加上括號,例如 Windows 裡的 WinDef.h 中就有定義得很嚴謹的max(a,b)


#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif

6 則留言:

  1. 小弟受益大大的blog許多,雖然這篇已經很久了,看到有小問題想詢問一下
    1. inline request是由compiler來決定要不要inline,而不是由preprocessor?
    1. 似乎是define在class中的member function才是預設inline的,而不是define在.h。

    回覆刪除
    回覆
    1. 婀不好意思排版有點跑掉

      刪除
    2. 這是初學 C++ 時做的紀錄,是該 review 一下了,謝謝您的細心,我查清楚後再來更新 :)

      刪除