第一部分:巨集
為什麼要使用巨集呢?
因為函式的呼叫必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去
執行該函式前的地方。這種轉移操作要求在轉去執行前要儲存現場並記憶執行的位址,轉回後要恢復現場,並按原來儲存位址繼續執行。因此,函式呼叫要有一定的時間和空間方面的開銷,於是將影響其效率。
而巨集只是在預處理的地方把**展開,不需要額外的空間和時間方面的開銷,所以呼叫乙個巨集比呼叫乙個函式更有效率。
但是巨集也有很多的不盡人意的地方。
在c語言中:
1、巨集容易出現一些邊界性的問題,產生二義性;
在c++中:
2、巨集又不可以呼叫c++類中的私有或者受保護的成員;
我們舉個例子:
#define square(x) (x*x)
我們用乙個數字去呼叫它,square(5),這樣看上去沒有什麼錯誤,結果返回25,是正確的,但是如果我們用squre (5+5)去呼叫的話,我們期望的結果是100,而巨集的呼叫結果是(5+5*5+5),結果是35,這顯然不是我們要得到的結果。避免這些錯誤的方法,一是給巨集的引數都加上括號。
#define square(x) ((x)*(x))
說明:巨集在呼叫的地方,僅僅是簡單的**替換,所以引數要用括號括起來,不會出現函式呼叫那種壓棧、出棧時的時間和空間的開銷,執行效率更高。
第二部分:內聯函式
從上面的闡述,可以看到巨集有一些難以避免的問題,對於不能訪問c++類中私有或者受保護的成員,我們應該如何解決呢?
內聯函式是**被插入到呼叫者**處的函式。如同 #define 巨集,內聯函式通過避免被呼叫的開銷來提高執行效率,尤其是它能夠通過呼叫(「過程化整合」)被編譯器優化。
內聯函式和巨集很類似,而區別在於,巨集是由
預處理器
對巨集進行替代,而內聯函式是通過
編譯器控制來實現的。而且內聯函式是真正的函式,只是在需要用到的時候,
內聯函式像巨集一樣的展開
,所以取消了函式的引數壓棧,減少了呼叫的開銷。你可以象呼叫函式一樣來呼叫內聯函式,而不必擔心會產生於處理巨集的一些問題。
內聯函式工作原理解釋:
對於任何內聯函式,編譯器在符號表裡放入函式的宣告(包括名字、引數型別、返回值型別)。
如果編譯器沒有發現內聯函式存在錯誤,那麼該函式的**也被放入符號表裡。
在呼叫乙個內聯函式時,編譯器首先檢查呼叫是否正確
(進行型別安全檢查,或者進行自動型別轉換,當然對所有的函式都一樣)。
如果正確,內聯函式的**就會直接替換函式呼叫,於是省去了函式呼叫的開銷。
這個過程與預處理有顯著的不同,因為預處理器不能進行型別安全檢查,或者進行自動型別轉換。
假如內聯函式是成員函式,物件的位址(this)會被放在合適的地方,這也是預處理器辦不到的。
宣告內聯函式看上去和普通函式非常相似:
void f(int i, char c);
當你定義乙個內聯函式時,在函式定義前加上 inline 關鍵字,並且將定義放入標頭檔案:
inline void f(int i, char c)
內聯函式必須是和函式體申明在一起,才有效。
像這樣的申明inline function(int i)是沒有效果的,編譯器只是把函式作為普通的函式申明,我們必須定義函式體。
inline int function(int i)
這樣我們才算定義了乙個內聯函式。我們可以把它作為一般的函式一樣呼叫。但是執行速度確比一般函式的執行速度要快。
當然,內聯函式也有一定的侷限性。
就是函式中的執行**不能太多了,如果,內聯函式的函式體過大,一般的編譯器會放棄內聯方式,而採用普通的方式呼叫函式。這樣,內聯函式就和普通函式執行效率一樣了。
有上面的兩者的特性,我們可以用內聯函式完全取代預處理巨集。
綜上:優點:
1)inline定義的內聯函式,函式**被放入符號表中,在使用時進行替換(像巨集一樣展開),效率很高。
2)類的內聯函式也是函式。編繹器在呼叫乙個內聯函式,首先會檢查引數問題,保證呼叫正確,像對待真正函式一樣,消除了隱患及侷限性。
3)inline可以作為類的成員函式,可以使用所在類的保護成員及私有成員。
缺點:內聯函式以複製為代價,活動產生開銷
1)如果函式的**較長,使用內聯將消耗過多記憶體 , 這種情況編譯器可能會自動把它作為非內聯函式處理
2)如果函式體內有迴圈,那麼執行函式**時間比呼叫開銷大。
inline與巨集的區別
區別如下:
1)內聯在編繹時展開,巨集在預編譯時展開。 展開的時間不同。
2)編譯內聯函式可以嵌入到目標**,巨集只是簡單文字替換。
3)內聯會做型別,語法檢查,而巨集不具這樣功能。
4)巨集不是函式,inline函式是函式
5)巨集定義小心處理巨集引數(一般引數要括號起來),否則易出現二義性,而內聯定義不會出現。
巨集與內聯函式
函式作為一種抽象機制,對解決大型複雜問題起到了很大作用。但是,由於函式呼叫時需要開銷的,例如,函式呼叫時需要保護呼叫者的執行環境,進行引數傳遞,執行呼叫命令,為區域性變數分配空間以及執行返回指令等,因此函式會帶來程式執行效率的下降,特別是對一些小函式的頻繁呼叫。c 提供了兩種解決上述問題的辦法 巨集...
巨集與內聯函式
建議 1 使用const定義常量而不是 define 2 使用inline內聯函式而不是 define來定義小型函式 第一部分 巨集 為什麼要使用巨集呢?因為函式的呼叫 必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去執行該函式前的地方。這種轉移操作...
巨集與內聯函式
第一部分 巨集 為什麼要使用巨集呢?因為函式的呼叫必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去執行該函式前的地方。這種轉移操作要求在轉去執行前要儲存現場並記憶執行的位址,轉回後要恢復現場,並按原來儲存位址繼續執行。因此,函式呼叫要有一定的時間和空...