程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 內聯函數之一

內聯函數之一

編輯:C++入門知識

在C中,保護效率的一個方法是使用宏( m a c r o )。宏可以不用普通函數調用就使之看起來像
函數調用。宏的實現是用預處理器而不是編譯器。預處理器直接用宏代碼代替宏調用,所以就沒有了參數壓棧、生成匯編語言的CALL、返回參數、執行匯編語言的RETURN的時間花費。
所有的工作由預處理器完成,因此,不用花費什麼就具有了程序調用的便利和可讀性。
C++中,使用預處理器宏存在兩個問題。第一個問題在C中也存在:宏看起來像一個函數調用,但並不總是這樣。這就隱藏了難以發現的錯誤。第二個問題是C++特有的:預處理器不容許存取私有(private)數據。這意味著預處理器宏在用作成員函數時變得非常無用。
為了既保持預處理器宏的效率又增加安全性,而且還能像一般成員函數一樣可以在類裡訪問自如,C + +用了內聯函數

1.預處理器存在的缺陷
預處理器宏存在的關鍵問題是我們可能認為預處理器的行為和編譯器的行為一樣。當然,
有意使宏在外觀上和行為上與函數調用一樣,因此容易被混淆
在宏調用中使用表達式作為參數時,當表達式在宏內展開,它們的優先級可能不同於我們所期望的優先級。這會產生些意想不到的問題。但是我們可以在編程的時候通過人為的方式來避免,給每一個表達式都加上一個括號。
利用宏對參數求值也會產生某些出乎意料的錯誤,因為它並不能完全模仿函數的行為
例如:
#define band(x) ((x)>5 && (x)<10? (x):0)
功能是判斷x是否位於5和10之間,是則返回x的值,否則返回0
int a=8;//顯然滿足條件
cout<<band(++a);
輸出的結果是0
因為宏展開時執行了兩次++a,第一次判斷(x)>5,此時a=9,第二次判斷(x)<10,此時a=10。所以最後返回的結果並沒用達到我們的預期。
對於C++,由於預處理器僅僅的簡單的執行原文替代,所以想在類中通過定義一個public的宏作為一個成員函數來對私有成員進行處理是不行的。

2.內聯函數
在解決C++中宏存取私有的類成員的問題過程中,所有和預處理器宏有關的問題也隨著消失了。這是通過使宏被編譯器控制來實現的。在C++中,宏的概念是作為內聯函數來實現的,而內聯函數無論在任何意義上都是真正的函數。唯一不同之處是內聯函數在適當時像宏一樣展開,所以函數調用的開銷被取消。因此,應該永遠不使用宏,只使用內聯函數。
任何在類中定義的函數自動地成為內聯函數,但也可以使用inline關鍵字放在類外定義的函數前面使之成為內聯函數。但為了使之有效,必須使函數體和聲明結合在一起,否則,編譯器將它作為普通函數對待。因此
inline int PlusOne(int x);
沒有任何效果,僅僅只是聲明函數(這不一定能夠在稍後某個時候得到一個內聯定義)。成功的方法如下:
inline int PlusOne(int x) { return ++x ;}
注意,編譯器將檢查函數參數列表使用是否正確,並返回值(進行必要的轉換)。這些事情是預處理器無法完成的。假如對於上面的內聯函數,我們寫成一個預處理器宏的話,將有不想要的副作用。
一般應該把內聯定義放在頭文件裡。當編譯器看到這個定義時,它把函數類型(函數名+返回值)和函數體放到符號表裡。當使用函數時,編譯器檢查以確保調用是正確的且返回值被
正確使用,然後將函數調用替換為函數體,因而消除了開銷。內聯代碼的確占用空間,但假如函數較小,這實際上比為了一個普通函數調用而產生的代碼(參數壓棧和執行C A L L)占用的空間還少。

在頭文件裡,內聯函數默認為內部連接——即它是static,並且只能在它被包含的編譯單元看到。因而,只要它們不在相同的編譯單元中聲明,在內聯函數和全局函數之間用同樣的名字也不會在連接時產生沖突。

 


3.類內部的內聯函數
在類內部定義內聯函數,inline關鍵字並不是必須的。任何在類內部定義的函數自動地為內聯函數。
當然,因為類內部的內聯函數節省了在外部定義成員函數的額外步驟,所以我們一定想在類聲明內每一處都使用內聯函數。但應記住,內聯的目的是減少函數調用的開銷。假如函數較大,那麼花費在函數體內的時間相對於進出函數的時間的比例就會較大,所以收獲會較小。而且內聯一個大函數將會使該函數所有被調用的地方都做代碼復制,結果代碼膨脹而在速度方面獲得的好處卻很少或者沒有。

 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved