內聯函式與巨集

2021-09-21 14:03:44 字數 1871 閱讀 6556

inline工具是c++新增的特性,c語言使用預處理器語句#define來提供巨集——內聯**的原始實現。

首先我們先看段**,試想下執行的結果

inline double inlsquare(double x) 

#define defsquare(x)x*x;

int main()

執行結果:

inline  s1 = 4

#define s2 = 4

inline s3 = 25

#define s4 = 11

inline s5 = 25

#define s6 = 25

inline s7 = 36

#define s8 = 49

我們會看到有兩組值是不一樣的,分別是s3和s4; s7和s8。究竟是什麼導致這樣的結果呢?

內聯函式inlsquare方法

s3的執行步驟:s3 = ( 2.0 + 3.0 ) * ( 2.0 + 3.0 ) ; 

巨集defsquare方法

s4的執行步驟:s4 = 2.0 + 3.0 * 2.0 + 3.0  ;

內聯函式inlsquare方法

s7的執行步驟:s7 = ( ++5 ) * ( ++5 )=( 6 )*( 6 )= 36 ; 

(我也猜想過這樣的,僅僅是猜想: 第一步:5*5  ;第二步 ++(5*5);第三步:(++(5*5))  + ( 5 + 5 )。

任何乙個值都可以,貌似其他值也成立  )

巨集defsquare方法

s8的執行步驟:將d遞增兩次,然後再乘;s8 = (++( ++5 )) * (++( ++5 ))=( 7 )*( 7 )= 49 。

(對於s8的步驟,我表示很懵逼,一臉懵懂、二兩迷茫...... 希望有人能解釋下)

面試題

答:因為函式的呼叫必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的內容執行完後再返回到轉去執行該函式前的地方。這種轉移操作要求在轉去執行前要儲存現場並記憶執行的位址,轉回後要恢復現場,並按原來儲存位址繼續執行。因此函式呼叫要有一定的時間和空間方面的開銷,於是將影響其效率。而巨集只是在預處理的地方將**展開,不需要額外的空間和時間方面的開銷,所以呼叫乙個巨集比呼叫乙個函式更有效率。

a.巨集不能訪問物件的私有成員

b.巨集的定義很容易產生二義性

#define defsquare(x) x*x

如果用乙個數字去呼叫它,defsquare(10),沒問題,結果是100正確;但是如果用乙個表示式defsquare(10+10)去呼叫的話,我們期待的結果是400,但是巨集呼叫結果是(10+10*10+10),結果為120,錯誤。為了避免這些錯誤的方法,給巨集的引數都加上括號,

#define defsquare(x) ((x)*(x))

這樣在一定程度上可以保證能夠程式不出錯,但是對於有些情況還是不行,呼叫defsquare(a++),巨集展開式為(a++)*(a++),如果a=4,結果為4*4=16,a=6,而我們期望的是4*4=16,a=5.

內聯函式和巨集的區別在於:巨集是由預處理器對巨集進行替換的,而內聯函式是通過編譯器控制實現的。而且內聯函式是真正的函式,只是在需要用到的時候內聯函式像巨集一樣的展開,所以取消了函式的引數壓棧,減少了呼叫的開銷。所以可以像呼叫函式一樣來呼叫內聯函式,而不必擔心會產生像巨集出現的問題。

在c++中強制建議使用const來代替巨集常量,使用內聯函式來代替巨集函式。

const和內聯函式在進行編譯時不僅進行替換,而且還會進行引數型別檢測,提高了程式的安全性。

內聯函式可以是普通函式,也可以是類的成員函式;函式式巨集不能作為類的成員函式。

巨集與內聯函式

函式作為一種抽象機制,對解決大型複雜問題起到了很大作用。但是,由於函式呼叫時需要開銷的,例如,函式呼叫時需要保護呼叫者的執行環境,進行引數傳遞,執行呼叫命令,為區域性變數分配空間以及執行返回指令等,因此函式會帶來程式執行效率的下降,特別是對一些小函式的頻繁呼叫。c 提供了兩種解決上述問題的辦法 巨集...

巨集與內聯函式

建議 1 使用const定義常量而不是 define 2 使用inline內聯函式而不是 define來定義小型函式 第一部分 巨集 為什麼要使用巨集呢?因為函式的呼叫 必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去執行該函式前的地方。這種轉移操作...

巨集與內聯函式

第一部分 巨集 為什麼要使用巨集呢?因為函式的呼叫必須要將程式執行的順序轉移到函式所存放在記憶體中的某個位址,將函式的程式內容執行完後,再返回到轉去執行該函式前的地方。這種轉移操作要求在轉去執行前要儲存現場並記憶執行的位址,轉回後要恢復現場,並按原來儲存位址繼續執行。因此,函式呼叫要有一定的時間和空...