1. 程式人生 > >C++簡單概念系列(行內函數)

C++簡單概念系列(行內函數)

   C++語言博大精深,當然在博大的同時就有複雜的出現,最突出的就是概念多不容易弄明白。本人也是初學C++在此談點對一些概念的理解一來加深記憶,二來給各位看官做個參考。

  文中我會以譚浩強教授的《C++面向物件程式設計》(《面》)和《C++Primer第三版》(《P》)為引用加以說明,在此請對國內程式語言教程有偏見的朋友積點口德。

  首先請看《P》對inline函式提出的概念:inline函式給出了一種解決方案。若一個函式被指定為inline函式,則它將在程式中每個呼叫點上被“內聯地”展開

  這個概念就引出了兩個問題一個是解決方案另一個是內聯地展開。

  什麼是解決方案呢?《P》中又對這一概念作出瞭解釋:inline指示對編譯器來說只是個建議

。編譯器可以選擇和忽略該建議,因為把一個函式宣告為inline函式,並不見得真的適合在呼叫點上展開。也就是說編譯器對inline函式是有選擇性的,並不是程式設計師對一個函式聲明瞭inline,這個函式就必須是內聯的了。

  什麼是內聯地展開呢?《P》中對這個概念沒有作出解釋,《面》一書中有:程式呼叫inline函式時並不真正地執行函式的呼叫過程(如保留返回地址等處理),而是把函式程式碼嵌入程式地呼叫點。這樣可以大大減少呼叫成員函式地時間開銷。這裡一個是對行內函數呼叫的說明“嵌入”,一個是對內聯優點的說明“大大減少呼叫函式的時間開銷”。嵌入也可以理解為替換,就像巨集一樣可以直接對變數進行替換處理,當編譯器看見函式方法呼叫時,就用整個函式定義嵌入到函式方法呼叫的那個位置。例如:

  遇見display();就用它的定義void display() { cout << "Hello World" << endl; }去替換。這樣做就省去了函式呼叫所耗的時間。

  當然程式設計師最關心的還是什麼條件用行內函數什麼條件不用。

  《effectiveC++》作者指出inline函式不能濫用,更不能不用。但都沒有作出最終建議,在這裡我總結了幾條建議供大家參考:

  • 遞迴函式-不用
  • 包含迴圈等控制結構的函式-不用
  • 大於10行程式碼的函式(當然只對變數初始化的可以忽略)-不用
  • 小的,只有幾行程式碼的,經常呼叫的函式-可以用

  當然這些並不是硬性規定,因為inline只是一種對編譯器的建議,採用與否全看編譯器對程式碼的理解。如果你堅持在包含迴圈控制的函式中宣告inline,那編譯器完全可以忽略你的建議。我們又何必自討苦吃給編譯器增加麻煩呢?

  最後還應該注意兩點:(1)行內函數的宣告和定義需放在一個原始碼檔案中,也就是說不能讓宣告與實現一個在.h中一個在.cpp中。(2)類中成員函式都是隱式指示為行內函數,加inline和不加inline是一個意思。

 以下是VC++2005優化頁面中對inline的設定:

  圖中優化一項中除“禁用”外,其他O1、O2、OX三個選項都是對下圖中“行內函數展開”預設為Ob2,也就是編譯器自動選擇程式碼中哪些函式需要進行lnline,並不是只有被程式設計師宣告為inline函式的函式才內聯。

  如果你不需要編譯器自動選擇你可以在“行內函數展開”中選擇Ob1,也就是隻有程式設計師宣告為inline的函式才內聯。

  當然就如上面提到的雖然你選擇了Ob1但是編譯器還是可以忽略掉你的inline宣告。MSDN:編譯器將內聯展開選項和關鍵字視為建議。不保證函式將內聯展開。無法強制編譯器內聯特定函式。

  總結:簡單的記住兩點一個是行內函數只是一種對編譯器的建議,既然是建議就有采納和不採納之分。再一個就是行內函數的運用可以加快程式執行速度,當然這個速度具體加快多少我不得而知,但是這並不妨礙我們去認識它和去運用它。