inline函數和宏定義區別 整理

本文轉自http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29235952&id=4206608

   內聯函數和普通函數相比可以加快程序運行的速度,因爲不需要中斷調用,在編譯的時候內聯函數可以直接唄鑲嵌到目標代碼中。內聯函數要做參數類型檢查,這是內聯函數跟宏相比的優勢。

   inline是指嵌入代碼,就是在調用函數的地方不是跳轉,而是把代碼直接寫到那裏去。對於短小的代碼來說,inline可以帶來一定的效率提升,而且和C時代的宏函數相比,inline更安全可靠。可是這個是以增加空間消耗爲代價的。至於是否需要inline函數就需要根據你的實際情況取捨了。


inline一般只用於如下情況:
  (1)一個函數不斷被重複調用。
  (2)函數只有簡單的幾行,且函數不包含for、while、switch語句。

  ●一般來說,我們寫小程序沒有必要定義成inline,但是如果要完成一個工程項目,當一個簡單函數被調用多次時,則應該考慮用inline。
  ● 宏在C語言裏極其重要,而在C++裏用得就少多了。關於宏的第一規則是:絕不應該去使用它,除非你不得不這樣做。幾乎每個宏都表明了程序設計語言裏或者程序裏或者程序員的一個缺陷,因爲它將在編譯器看到程序的正文之前重新擺佈這些正文。宏也許是許多程序設計工具的麻煩。所以,如果你使用了宏,你就應該準備着只能從各種工具(如排錯系統、交叉引用系統、輪廓程序等)中得到較少的服務。(--pass:宏還是很方便的,使用時要小心,並不是說宏一無是處,存在自然有其合理性)

  宏是在代碼處不加任何驗證的簡單替代,而內聯函數是將代碼直接插入調用處,而減少了普通函數調用時的資源消耗。
  宏不是函數,只是在編譯前(編譯預處理階段)將程序中有關字符串替換成宏體。

  inline函數是函數,但在編譯中不單獨產生代碼,而是將有關代碼嵌入到調用處。

inline函數是C++引入的機制,目的是解決使用宏定義的一些缺點。
1.爲什麼要引入內聯函數(內聯函數的作用)
  用它替代宏定義,消除宏定義的缺點。宏定義使用預處理器實現,做一些簡單的字符替換因此不能進行參數有效性的檢測。另外它的返回值不能被強制轉換爲可轉換的合適類型,且C++中引入了類及類的訪問控制,在涉及到類的保護成員和私有成員就不能用宏定義來操作。
2.inline相比宏定義有哪些優越處
  (1)inline函數代碼是被放到符號表中,使用時像宏一樣展開,沒有調用的開銷效率很高;
  (2)inline函數是真正的函數,所以要進行一系列的數據類型檢查;
  (3)inline函數作爲類的成員函數,可以使用類的保護成員及私有成員;
3.inline函數使用的場合
  (1)使用宏定義的地方都可以使用inline函數;
  (2)作爲類成員接口函數來讀寫類的私有成員或者保護成員;
4.爲什麼不能把所有的函數寫成inline函數
  內聯函數以代碼複雜爲代價,它以省去函數調用的開銷來提高執行效率。所以一方面如果內聯函數體內代碼執行時間相比函數調用開銷較大沒有太大的意義;另一方面每一處內聯函數的調用都要複製代碼,消耗更多的內存空間,
因此以下情況不宜使用內聯函數。
  (1)函數體內的代碼比較長,將導致內存消耗代價;
  (2)函數體內有循環,函數執行時間要比函數調用開銷大;

  另外類的構造與析構函數不要寫成內聯函數。

5.內聯函數與宏定義區別
  (1)內聯函數在編譯時展開,宏在預編譯時展開;
  (2)內聯函數直接嵌入到目標代碼中,宏是簡單的做文本替換;
  (3)內聯函數有類型檢測、語法判斷等功能,而宏沒有;
  (4)inline函數是函數,宏不是;
  (5)宏定義時要注意書寫(參數要括起來)否則容易出現歧義,內聯函數不會產生歧義;

inline的使用是有所限制的,inline只適合函數體內代碼簡單的涵數使用,不能包含複雜的結構控制語句例如while、switch,並且不能內聯函數本身不能是直接遞歸函數(自己內部還調用自己的函數)。
補充:

inline函數僅僅是一個建議,對編譯器的建議,所以最後能否真正內聯,看編譯器的意思,它如果認爲函數不復雜,能在調用點展開,就會真正內聯,並不是說聲明瞭內聯就會內聯,聲明內聯只是一個建議而已。
其次,因爲內聯函數要在調用點展開,所以編譯器必須隨處可見內聯函數的定義,要不然,就成了非內聯函數的調用了。所以,這要求每個調用了內聯函數的文件都出現了該內聯函數的定義。

因此,將內聯函數放在頭文件裏實現是合適的,省卻你爲每個文件實現一次的麻煩。而所以聲明跟定義要一致,其實是指,如果在每個文件裏都實現一次該內聯函數的話,那麼,最好保證每個定義都是一樣的,否則,將會引起未定義的行爲,即是說,如果不是每個文件裏的定義都一樣,那麼,編譯器展開的是哪一個,那要看具體的編譯器而定。所以,最好將內聯函數定義放在頭文件中。
而類中的成員函數缺省都是內聯的,如果在類定義時就在類內給出函數,那當然最好。如果在類中未給出成員函數定義,而又想內聯該函數的話,那在類外要加上inline,否則就認爲不是內聯的。

爲了方便,將內聯函數直接聲明時就定義,放在頭文件中。這樣其它文件包含了該頭文件,就在每個文件都出現了內聯函數的定義。就可以內聯了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章